golang(2):基本数据类型和操作符

1). 文件名 & 关键字 & 标识符

1. 所有go源码都以 .go 结尾
2. 标识符以字母或下划线开头,大小写敏感
3. _ 是特殊标识符,用来忽略结果
4. 保留关键字

golang 关键字如下:

包中函数的调用:

a. 同一个包中的函数,可直接调用 (大小写都可以)
b. 不同包中的函数,通过 包名 + 点 + 函数名进行调用 (函数名的首字母必须大写)

包访问控制规则:

a. 大写意味着这个函数/变量是可导出的
b. 小写意味着这个函数/变量是私有的,包外部不能访问

示例1:写一个程序,对于给定一个数字n,求出所有两两相加等于n的组合。

代码如下:

package main

import (
    "fmt"
)

func handle(n int){
    for i := 0;i<=n;i++ {
    fmt.Printf("%d+%d=%d
",i,n-i,n)   //  fmt.Printf()  是格式化输出
    }
}

func main(){
    handle(5)
}

编译运行:

[root@NEO project]# go build -o bin/example01_plus go_dev/day02/example01_plus/main
[root@NEO project]# bin/example01_plus 
0+5=5
1+4=5
2+3=5
3+2=5
4+1=5
5+0=5
[root@NEO project]# 

示例2:一个程序包含两个包 add 和 main,其中 add 包中有两个变量: Name 和 age。问 main 包中如何访问 Name 和 age?

# 目录结构如下:
[root@NEO day02]# tree example02_call_var01
example02_call_var01
├── add
│   └── add.go
└── main
    └── main.go

2 directories, 2 files
[root@NEO day02]# 


示例代码如下:
# 方式1:
main.go 文件:
package main

import (
    "go_dev/day02/example02_call_var01/add"
    "fmt"
)

func main(){
    fmt.Println("Name=",add.Name)
    fmt.Println("Age=",add.Age)
}

add.go 文件:
package add

var Name string = "hello world"   // 声明变量,并对变量的值进行初始化(编译时);字符串如果只声明却没初始化,则该字符串变量的值为 空
var Age int = 10        // 字符串如果只声明却没初始化,则该字符串变量的值为 0

# 编译之后的运行结果如下:
[root@NEO bin]# ./example0201 
Name= hello world
Age= 10
[root@NEO bin]# 

# 方式2:
main.go 文件:
package main

import (
    "go_dev/day02/example02_call_var02/add"
    "fmt"
)

func main(){
    add.Var_test()    // 先调用 该函数来对变量 Name 和 Age 进行初始化
    fmt.Println("Name=",add.Name)
    fmt.Println("Age=",add.Age)
}

add.go 文件:
package add

var Name string
var Age int

func Var_test(){   // 首字母要大写
    Name = "hello world"    // go 是编译型语言,所有的执行语句都要放到函数里面(赋值/初始化也是执行语句)
    Age = 10
}


# 错误示例:
main.go 文件内容:
package main

import (
    "go_dev/day02/example02_call_var03_err/add"
    "fmt"
)

function main(){
    fmt.Println("Name=",add.Name)
    fmt.Println("Age=",add.Age)
}

add.go 文件内容:
package add

var Name string 
var Age int    

Name = "hello world"  // go 是编译型语言,所有的执行语句都要放到函数中作为入口
Age = 10 

示例3:包别名的应用:开发一个程序,使用包别名来访问包中的函数

# main.go示例如下:
package main

import (
    a "go_dev/day02/example02_call_var01/add"    // 给go_dev/day02/example02_call_var01/add这个包起一个别名 a
    "fmt"
)

func main(){
    fmt.Println("Name=",a.Name)  // 使用包的别名来调用包中的函数
    fmt.Println("Age=",a.Age)
}

示例4:每个源文件都可以包含一个 init  函数,这个init函数自动被go运行框架调用。写一个程序演示这个功能

# 演示代码如下:
// main.go 文件内容:
package main

import (
    a "go_dev/day02/example02_call_var02_init/add"
    "fmt"
)

func main(){    // init 函数会在 main 函数执行之前先被调用
    fmt.Println("Name=",a.Name)
    fmt.Println("Age=",a.Age)
}

// add.go 文件内容:
package add

import (
    "fmt"
)

var Name string = "xxxx"
var Age int = 100

func init(){   // init 函数会在 main 函数执行之前先被调用 
    fmt.Println("initiated====>")
    Name = "hello world"    
    Age = 10
}

# 执行结果:
[root@NEO example02_call_var02_init]# go run main/main.go 
initiated====>
Name= hello world
Age= 10
[root@NEO example02_call_var02_init]# 

// 执行顺序:1. 初始化全局变量; 2. 调用 init 函数 ;3. 调用 main 函数


# 导入多个包的示例如下:
目录结构如下:
[root@NEO day02]# tree example02_call_var02_init
example02_call_var02_init
├── add
│   └── add.go
├── main
│   └── main.go
└── test
    └── test.go

3 directories, 3 files
[root@NEO day02]# 

# 示例代码如下:
# main.go 文件内容:
package main

import (
    a "go_dev/day02/example02_call_var02_init/add"
    "fmt"
)

func main(){    // init 函数会在 main 函数执行之前先被调用
    fmt.Println("Name=",a.Name)
    fmt.Println("Age=",a.Age)
}


# add.go 文件内容:
package add

import (
    _ "go_dev/day02/example02_call_var02_init/test"  // 如果导入一个包只是为了初始化,并没有用到这个包中的变量或者函数,要在导入这个包时,在包的前面加上下划线 _ ;如果导入的这个包中的变量或者函数有被引用,则不需要加 _
    "fmt"
)

var Name string = "xxxx"
var Age int = 100

func init(){   // init 函数会在 main 函数执行之前先被调用 
    fmt.Println("initiated====>")
    Name = "hello world"    
    Age = 10
}

# test.go 文件内容:
package test

import(
    "fmt"
)

var Name string = "this is test pkg"    // 变量的区分是包名 + 变量名,这个包中的 Name变量是 test.Name,和 add 包中的 Name变量是不同的变量
var Age int = 18

func init(){
    fmt.Println("this is test initiated")
    fmt.Println("test.Name=",Name)
    fmt.Println("test.Age=",Age)

    Age = 20 
    fmt.Println("test.Age=",Age)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/test_multi_init go_dev/day02/example02_call_var02_init/main
[root@NEO project]# bin/test_multi_init 
this is test initiated
test.Name= this is test pkg
test.Age= 18
test.Age= 20
initiated====>
Name= hello world
Age= 10
[root@NEO project]# 

函数声明和注释

# 1. 函数声明: func (函数名) (参数列表) (返回值类型列表) {}
# 2. 注释方式有两种:
      单行注释: //
      多行注释: /* */

常量

1. 常量使用 const 修饰,代表永远是只读的,不能修改
2. const 只能修饰 boolean ,number (int 相关类型、浮点型、complex)和 string
3. 语法: const identifier [type] = value ,其中 type 可以省略
举例如下:
    # 写法1:
    const b string = "hello world"
    const b = "hello world"
    const Pi = 3.1414926
    const a = 9/3
    
    # 错误示例:
    const c = getValue()  // 常量不能这样通过函数直接赋值
    
    # 写法2:
    const(
        a = 0
        b = 1
        c = 2
    )

    # 写法3:
    const(
        a = iota    // a 是 0 
        b    // 此时 a 后面的常量会自动 加 1,所以 b 为 1
        c    // c 为 2
    )

示例5: 定义两个常量 Man=1 和 Female=2,获取当前时间的秒数,如果能被 Female 整除,则在终端打印 female,否则打印 man

// 获取当前秒数(时间戳): second := time.Now().Unix()

# 示例代码如下:
package main

import (
    "fmt"
    "time"
)

const (
    Man = 1
    Female = 2
)

func main(){
    for {
    second := time.Now().Unix()    // 时间戳
    if (second % Female == 0){
        fmt.Println("female")
    } else {
        fmt.Println("man")
    }
    time.Sleep(1000 * time.Millisecond)    // time.Millisecond 代表 1 毫秒, time.Microsecond 代表 1 微秒
    }
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example02_const01 go_dev/day02/example02_const01/main
[root@NEO project]# bin/example02_const01 
man
female
man
female
man
^C
[root@NEO project]# 

变量

# 1. 语法: var identifier type
# 举例如下:
    # 写法1:
    var a int
    var b string
    var c bool
    var d int = 8
    var e string = "hello world"

    # 写法2:
    var(
        a int         // 默认为 0 
        b string    // 默认为 "" 空
        c bool        // 默认为 false
        d int = 8
        e string = "hello world"
    )

    # 写法3:
    var(
        a int         // 默认为 0 
        b string    // 默认为 "" 空
        c bool        // 默认为 false
        d = 8
        e = "hello world"
    )

示例6:写一个程序获取当前运行的操作系统名称和PATH环境变量的值,并打印在终端

# 示例代码如下:
package main

import(
    "fmt"
    "os"    // os 是系统包
)

func main(){
    // os.Getenv() 是获取系统变量
    var goos string = os.Getenv("GOOS")
    fmt.Printf("The operating system is: %s
",goos)

    var path = os.Getenv("PATH")
    fmt.Printf("Path is: %s
",path)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example04_var01  go_dev/day02/example04_var01/main
[root@NEO project]# bin/example04_var01 
The operating system is: 
Path is: /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/go/bin:/root/bin
[root@NEO project]# 

值类型和引用类型

# 1. 值类型:变量直接存储值,内存通常在栈中分配
         var i = 5  ===> i --> 5
     在 golang中,基本数据类型 int , float, bool, string 以及 数组 和 struct 都是 值类型
    在函数内部,假如修改了 值类型 变量的值,那么在函数外面,该变量的值不会改变
# 2. 引用类型:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配。通过 GC 回收
          ref ---> 地址 ---> 值 
     在 golang 中,指针、 slice、 map、 chan、函数等都是引用类型 
     在函数内部,假如修改了 引用类型 变量的值,那么在函数外面,该变量的值也会改变

示例7:写一个程序用来打印值类型和引用类型到终端,并观察输出结果

# 代码如下:
package main

import(
    "fmt"
)

func modify_val(a int){   // a 是 int 类型的值类型变量
    a = 10    // 值变量作为函数的形参传参时,该变量会 拷贝 一份传到函数中,在函数中对该变量修改时,修改的是拷贝的这个变量,不会影响函数外该变量原先的值
}

func modify_cite(a *int){  // a 是 指针类型的引用类型; *数据类型 表示 指针 
    *a = 15    // *a 表示的是 指针a 所指向的那块内容中的值(即指针a实际的值)
}

func main(){
    a := 5
    b := make(chan int,1)

    fmt.Println("a=",a)
    fmt.Println("b=",b)

    modify_val(a)
    fmt.Println("value of int a after modify is:",a)    // 值类型的变量 a 在函数内修改后不会改变函数外部 a 的值

    modify_cite(&a)    // &a 表示传入的是一个地址
    fmt.Println("value of cite a is:",a)    // 在 modify_cite 函数中修改 指针a指向地址指向的值后,函数外部该指针的值也会变

}

# 编译运行后结果如下:
[root@NEO project]# go build -o bin/example04_var02 go_dev/day02/example04_var02/main
[root@NEO project]# bin/example04_var02 
a= 5
b= 0xc000046070            # 引用类型的变量中存的是一个地址,这个地址指向的才是真正的存储内容的值
value of int a after modify is: 5
value of cite a is: 15
[root@NEO project]# 

示例8:写一个程序,交换两个整数的值。比如: a=3; b=4; 交换之后: a=4; b=3

// 错误示例:
package main

import(
    "fmt"
)

func swap(a int,b int){
    tmp := a
    a = b
    b = tmp
    return
}

func main(){
    first := 1
    second := 2
    swap(first, second)     // 这种写法并不能在函数 swap 外实现 first 和 second 值的互换;对于 值类型的变量在函数传参时会对参数先 拷贝 一份,拷贝后是一个新的独立的内存地址,在函数内对这些变量修改时,是对 拷贝后的值(复本的值)进行修改,不会影响函数外这些变量的值
    fmt.Println("first=",first)
    fmt.Println("second=",second)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example04_var03_err go_dev/day02/example04_var03_err/main
[root@NEO project]# bin/example04_var03_err 
first= 1        # 两个变量的值未交换
second= 2
[root@NEO project]# 

// 正确示例:
// 方式一:
package main

import(
    "fmt"
)

func swap(a *int,b *int){    // *数据类型 表示 指针 
    tmp := *a    // *a 表示的是 指针a 所指向的那块内容中的值(即指针a实际的值); a前面不加 * 就表示一个地址
    *a = *b    // 把 b指针实际的值 赋值给 a指针实际的值
    *b = tmp    // 把 tmp 变量对应的值 赋值给 b指针实际的值
    return
}

func main(){
    first := 1
    second := 2
    swap(&first, &second)    // &first 表示传入的是一个地址
    fmt.Println("first=",first)
    fmt.Println("second=",second)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example04_var0301 go_dev/day02/example04_var0301/main
[root@NEO project]# bin/example04_var0301 
first= 2        # 两个变量的交换
second= 1
[root@NEO project]# 

# 函数在传参时,会把变量先拷贝一份(复本),然后传参时传的都是变量的复本(包括传引用变量的地址时,也是先拷贝一份引用变量地址的复本,但源引用变量的地址和复本引用变量的地址指向的是同一块内存空间,即指向同一个值)


// 方式二:
package main

import(
    "fmt"
)

// 通过返回值的方式
func swap(a int,b int) (int, int){
    return b,a
}

func main(){
    first := 1
    second := 2
    first,second = swap(first, second) 
    fmt.Println("first=",first)
    fmt.Println("second=",second)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example04_var0302 go_dev/day02/example04_var0302/main
[root@NEO project]# bin/example04_var0302 
first= 2
second= 1
[root@NEO project]# 

// 方式三:
package main

import(
    "fmt"
)


func main(){
    first := 1
    second := 2

    first, second = second, first  // 变量直接互换

    fmt.Println("first=",first)
    fmt.Println("second=",second)
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example04_var0303 go_dev/day02/example04_var0303/main
[root@NEO project]# bin/example04_var0303 
first= 2
second= 1
[root@NEO project]# 

变量的作用域

1. 在函数内部声明的变量叫局部变量,生命周期仅限于函数内部
2. 在函数外部声明的变量叫全局变量,生命周期作用于整个包,如果是大写的,则可以在包外部访问
3. 声明在语句块({ })中的变量也是局部变量,其作用域也是在这个语句块({})中

// 示例代码1:
package main

import (
    "fmt"
)

var a = "G"        // a 是 全局变量

func main(){
    n()
    m()
    n()
}

func n(){
    fmt.Println(a)
}

func m(){
    a = "M"        // 在函数内部对全局变量的值进行修改
    fmt.Println(a)
}

# 运行结果如下:
[root@NEO example04_var0304_scope]# go run main/main.go 
G
M
M
[root@NEO example04_var0304_scope]# 

// 示例代码2:
package main

import (
    "fmt"
)

var a = "G"

func main(){
    n()
    m(a)   // 传参时是先拷贝一份参数的复本,然后把参数的复本传进去
    n()
}

func n(){
    fmt.Println(a)
}

func m(a string){
    a = "M"            // 对复本进行修改
    fmt.Println(a)
}

# 运行结果如下:
[root@NEO example04_var0304_scope02]# go run main/main.go
G
M
G
[root@NEO example04_var0304_scope02]# 

// 示例代码3:
package main

import (
    "fmt"
)

var a string

func main(){
    a = "G"   // 对全局变量a进行赋值
    fmt.Println(a)
    f1()
}

func f1(){
    a := "f1"   // 此处声明(定义)了一个局部变量 a;而不是对全局变量 a 重新赋值(a = "f1")
    fmt.Println(a)
    f2()
}

func f2(){        
    fmt.Println(a)        // f2 函数中没有变量 a ,会从全局变量中取 (f2 的作用域和f1的作用域没有关系)
}

// 运行结果如下:
[root@NEO example04_var0304_scope03]# go run main/main.go
G
f1
G        // f2 函数取的是全局变量的 a   
[root@NEO example04_var0304_scope03]# 

// 示例代码4:
package main

import (
    "fmt"
)

var a string

func main(){
    a = "G"   // 对全局变量a进行赋值
    fmt.Println(a)
    f1()
}

func f1(){
    a := "f1"   // 此处声明(定义)了一个局部变量 a
    fmt.Println(a)
    f2(a)
}

func f2(a string){
    fmt.Println(a)
}

// 运行结果如下:
[root@NEO example04_var0304_scope04]# go run main/main.go 
G
f1
f1
[root@NEO example04_var0304_scope04]# 

数据类型和操作符

1. bool 类型,只能存 truefalse
    // 示例:
    var a bool
    var a bool = true
    var a = true
    
2. 相关操作符: ! 、&& 、||

3. 数字类型,主要有 int 、int8 、int16 、int32 、int64 、uint8 、uint16 、uint32 、uint64 、float32 、float64

4. 类型转换, type(variable) ,比如: var a int = 8var b int32 = int32(a)
// 示例:
package main
func main(){
    var a int
    var b int32
    a = 15
    b = b + 5    // 这行代码能正常编译
    b = a + a    // 这行代码会报错,因为 a 和 b 不是同一种类型的 int;解决方法是类型转换: 利用 int32(a) 把 a 也转换为 int32 类型 ---> b = int32(a) + int32(a)
}

5. 字符类型: (byte 型, 或者叫 uint8 类型,代表了 ASCII 码的一个字符。)
    var a byte       
    var a byte = 'c'    // 字符 byte 只能用 单引号 
    // byte 是一个字符

    
6. 字符串类型:
    var str string
    // 字符串的两种表示方式:
        1. 双引号            // 双引号会对字符串中的内容进行转义,如 

        2. ``  (反引号)    // `` 不会对字符串中的内容进行转义处理,即 所见即所得;而且 反引号中的字符串能进行 换行
// 字符串的双引号和反引号示例代码如下:
package main

import(
    "fmt"
)

func main(){
    var str1 = "hello world 

"
    var str2 = `hello 
 n 

this is a test string
this is a test string too`
    fmt.Println("str1=",str1)
    fmt.Println("str2=",str2)

    var c byte = 'c'    // c 的本质是一个数字:该字符在 ASCII 中对应的数字
    fmt.Println("byte c =",c)    
    fmt.Printf("%c
",c)    // 格式化输出中, %c 表示 输出单个字符
}

// 编译之后的运行结果如下:
[root@NEO project]# go build -o bin/example06_str go_dev/day02/example06_str/main
[root@NEO project]# bin/example06_str 
str1= hello world 


str2= hello 
 n 

this is a test string
this is a test string too
byte c = 99
c
[root@NEO project]# 



# 补充:
//在全局区域:
var a int = 100  // 声明一个变量 a 为 int 类型,并初始化为 100;这一行代码放到 全局区域 是完全没问题的

// 但下面的代码放到全局区域则会报错:
var a int    // 声明变量 a 为 int ;这行代码没有错
a = 100        // 赋值操作

// 报错原因: 赋值操作也是在执行代码,但全局区域能声明变量,但不能执行代码,执行代码要放到函数中

逻辑操作符: == 、!= 、 < 、 <= 、 > 、 >=
数学操作符: + 、 - 、 * 、 / 、等等

示例9:使用 math/rand 生成10个随机整数,10个小于100的随机整数以及10个随机浮点数 (随机数

// rand 包实现了伪随机数生成器;
// 随机数由一个 Source 生成。像 Float64 和 Int 这样的顶级函数使用默认共享的 Source, 它会在每次程序运行时产生一系列确定的值。若每次运行都需要不同的行为,需使用 Seed 函数来初始化默认的 Source。

// 随机数由一个 Source 生成;使用 Seed 函数来初始化默认的 Source

// 示例代码:
package main

import (
    "fmt"
    "math/rand"
    "time"
)

func init(){
    rand.Seed(time.Now().UnixNano())   // 利用当前纳秒时间戳 设置 种子
}

func main(){
    for i :=0;i<10;i++{
    a := rand.Int()  // Int() returns a non-negative pseudo-random int from the default Source.
    fmt.Println(a)
    }

    for i :=0;i<10;i++ {
    a := rand.Intn(100)    // Intn(n) returns, as an int, a non-negative pseudo-random number in [0,n) from the default Source. It panics if n <= 0.
    fmt.Println(a)
    }

    for i :=0;i<10;i++ {
    a := rand.Float32()    // Float32() returns, as a float32, a pseudo-random number in [0.0,1.0) from the default Source.
    fmt.Println(a)
    }
}

# 编译之后的运行结果如下:
[root@NEO project]# go build -o bin/example05_rand go_dev/day02/example05_rand/main
[root@NEO project]# bin/example05_rand 
6490486822796045968
9144196389670471465
6917284983782713832
6708046869565845710
6979317820484376884
7814095851982680867
8062397337643966196
6169353628608003521
6637280047299576259
8924964441859908871
73
96
8
89
25
72
86
27
53
42
0.87334687
0.34517118
0.82716334
0.49546078
0.74162775
0.4064283
0.72067785
0.277449
0.95820624
0.4750664
[root@NEO project]# 

格式化输出:

// 示例代码:
package main

import(
    "fmt"
)

func main(){
    var a int
    var b bool
    var c byte = 'c'
    d := 'd'    // d 是 byte 类型

    fmt.Printf("%v
",a)    // 相应值的默认格式。在打印结构体时,“加号”标记(%+v)会添加字段名
    fmt.Printf("%v
",b)    // %v 就是以原样打印出来(不知道怎么输出时就用 %v)
    fmt.Printf("%v
",c)    
    
    fmt.Printf("%+v
",a)        // 在打印结构体时,“加号”标记(%+v)会添加字段名
    fmt.Printf("%#v
",b)        // %#v  ---> 相应值的Go语法表示
    fmt.Printf("%#v
",c)

    fmt.Printf("%T
",b)    // %T ---> 相应值的类型
    fmt.Printf("%T
",d)    

    fmt.Printf("90%%
")    // %% ---> 字面上的百分号,并非值的占位符(转义)

    fmt.Printf("%t
",b)    // %t ---> 单词 true 或 false。(bool 型)

    fmt.Printf("%b
",100)    // %b ---> 打印其二进制

    fmt.Printf("%f
", 199.22)      // %f ---> 浮点型

    fmt.Printf("%q
", "this is a test")   // 双引号围绕的字符串,由Go语法安全地转义 (带双引号的字符串)
    fmt.Printf("%x
", 39839333)    // %x ---> 十六进制(十六进制,小写字母,每字节两个字符)
    fmt.Printf("%p
", &a)        // %p ---> 十六进制表示,前缀 0x ; &a 表示其地址

    a = 100

    str := fmt.Sprintf("a=%d", a)    // Sprintf ---> S 表示返回字符串
    fmt.Printf("%q
", str)
}


// 编译之后的运行结果如下:
[root@NEO project]# go build -o bin/example07_fmt go_dev/day02/example07_fmt
[root@NEO project]# bin/example07_fmt 
0
false
99
0
false
0x63
bool
int32
90%
false
1100100
199.220000
"this is a test"
25fe665
0xc0000120a8
"a=100"
[root@NEO project]# 

字符串操作:

// 示例代码:
package main

import(
    "fmt"
)

func reverse(str string) string {
    // 字符串反转函数

    var result string
    strLen := len(str)
    for i:=0; i<strLen; i++ {
    result = result + fmt.Sprintf("%c",str[strLen-1-i])
    }
    return result
}


func main(){
    var str1 = "hello"
    str2 := "world"

    // 字符串拼接
    str3 := str1 + " " + str2
    fmt.Println(str3)

    str4 := fmt.Sprintf("%s %s",str1,str2)
    fmt.Println(str4)

    n := len(str4)    // 字符串长度
    fmt.Printf("length of str4 is %d
",n)
   
    substr := str4[0:5]      // 字符串截取  // 同一个变量只能声明一次
    fmt.Println(substr)

    result := reverse(str3)
    fmt.Println(result)
}

// 编译后执行结果如下:
[root@NEO project]# go build -o bin/example06_str02 go_dev/day02/example06_str02/main
[root@NEO project]# bin/example06_str02
hello world
hello world
length of str4 is 11
hello
dlrow olleh
[root@NEO project]# 

示例: 打印出 100~999 中所有的 “水仙花数”,水仙花数 是指一个三位数,其各位数字立方和等于该数本身。例如: 153 = 1**3 + 5**3 + 3**3

# 示例代码如下:
package main

import "fmt"

func isNumber(n int) bool {
    var i,j,k int
    i = n % 10        // 个位
    j = (n/10) % 10    // 十位
    k = (n/100) % 10    // 百位

    sum := i*i*i + j*j*j + k*k*k

    return n == sum
}

func main(){
    for i:=100; i <= 999; i++ {
    if isNumber(i) == true{
        fmt.Println(i,"is shuixianhuashu")
    } else {
        fmt.Println(i,"not shuixianhuashu")
    }
    }
}

# 编译后执行结果如下:
[root@NEO project]# go build -o bin/example08_square go_dev/day02/example08_square/main
[root@NEO project]# bin/example08_square |grep is
153 is shuixianhuashu
370 is shuixianhuashu
371 is shuixianhuashu
407 is shuixianhuashu
[root@NEO project]# 

// fmt.Scanf() ---> 读取终端输入,如: fmt.Scanf("%d",&num)      ---> 内部如果需要改 num 的值,就传入这个参数的地址;如果不需要修改 num 的值,直接传num 这个变量就行

fmt.Scanf() 示例:

package main

import (
    "fmt"
)

func main (){
    var s string

    fmt.Printf("default:%s
",s)

    fmt.Scanf("%s
",s)
    fmt.Printf("s without &:%s
",s)

    fmt.Scanf("%s
",&s)
    fmt.Printf("s with &:%s",s)

}

运行结果如下:

[root@NEO ~]# go run main.go 
default:
a
s without &:
s with &:[root@NEO ~]# 
[root@NEO ~]# go run main.go 
default:
a b
s without &:
s with &:b
[root@NEO ~]#

// 所以在用 fmt.Scanf() 接收外部变量时, 传入的变量前要加上 &
原文地址:https://www.cnblogs.com/neozheng/p/11167021.html