在go语言中的代码文件中最上层会定义一个package声明开头,说明源文件所属的包

而后使用Import导入依赖的包,其次为包级别的变量,产量,类型和函数的什么和赋值

函数中可定义局部的变量和常量等。

如下:

package main
import "fmt"
func main(){
  fmt.Println("hello world!")
}

package main 中的main是程序的入口。在后面的包管理中会有其他的方式表示

1.helo world#

run#

通常我们可以使用go run go文件来运行一个go文件。如:

[root@LinuxEA /opt/Golang]# go run 01.go 
[root@LinuxEA /opt/Golang]# go run 01.go 
hello world

windows

E:\golang\project\src\Golang>go run main.go
hello world!

build#

我们可以使用build来编译

[root@LinuxEA /opt/Golang]# go build 01.go 

而后就会多出来一个main.exe 在这个案例中,运行main.exe和go run main.go一样

windows

E:\golang\project\src\Golang>go build main.go

E:\golang\project\src\Golang>main.exe
hello world!

linux

[root@LinuxEA /opt/Golang]# ./01
hello world

注释#

通常我们使用双斜线来注释一行代码,或者使用/*和*/来注释一大块的代码,如下:

代码的注释也可以在代码的第一行

// 我也是注释
package main
import "fmt"
func main(){
    fmt.Println("hello world!")

    // 双斜杠可以注释一行

    /* 
    多行注释
    fmt.Println("hello world!")
    fmt.Println("hello world!")
    */
}

2.程序组成的基本单位#

这和其他的语言一般无二。

标识符#

标识符是编程时候使用的名字,这个名字可以是变量,产量,函数,类型,接口,包,以及后续的结构体都是由名字组成

最终访问的也是通过标识符名字访问的。通过标识符建立名称和使用的关系。

!!! note

在go语言中的标识符有非空的字母组成(unicode),数字,下划线(_)组成

unicode意味着可以使用中文命名,但是并不建议这么做。

!!! note

不能使用GO的关键字

go语言中有25个关键字不可以使用:

声明:import,package

实体声明和定义:chan,const,func,interface,map,struct,type,var

流程控制: break,case,continue,default,defer,else,fallthrough,for,go,goto,if,range,return,select,switch

内置产量:true,false,nil,iota 内置类型: bool,byte,rune,int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,uintptr,float32,float64,complex64,complex128,string,error 内置函数:make,len,cap,new,append,copy,close,delete,panic,recover,complex,real,imag 空白标识符: _

myNameIs := 
My
my

字面量#

当创建一个linuxea后定义一个字符串类型的变量去赋值,这时候linuxea就是字面量

字面量是值的表示方法,常用与对变量/产量进行初始化。

主要分为:

操作符#

如下:

算数运算符:+,-,*,/,%,++,-- (加,减,乘,除,余,自增,自减)

关系运算符:>,>=,<,<=,==,!= (大于,大于等于,小于,小于等于,等于,不等于)

逻辑运算符:&&,||,! (且,或,非)

位运算符:&,|,^,<<,>>,&^ (与,或,取反,左移,右移,按位清除 )

赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>= (符合赋值)

其他运算符:&(),*(),.(),-(),...,<- (取地址,取引用,方法调用/属性获取,符号位取反,..., 管道读写)

分隔符#

小括号(),中括号[],大括号(),分号;,逗号,

3.变量语法声明#

声明语句用于定义程序的各种实体对象,如:

变量#

什么是变量?

变量是值对一块存储空间的定义名称 ,通过名称对存储空间的内容进行访问或者修改。变量声明的常见语法:

变量的声明必须满足标识语法:

1,定义一个me的变量,并指定变量类型

2,赋值me 值为linuxea.com

需要满足标识符的命名规则。

    var me string
    me = "linuxea.com"

如下:

[root@LinuxEA /opt/Golang]# cat 02.go
package main
import "fmt"
func main(){
    var me string
    me = "linuxea.com"
    fmt.Println(me)
}

!!! 警告

注意:函数体内的变量必须使用,否则会报错

运行

[root@LinuxEA /opt/Golang]# go run 02.go 
linuxea.com

函数外变量#

现在我们在函数之外定义一个变量,使用等号=进行赋值

!!! note

如果定义的变量没有赋值,就会自动赋值一个零值
var version string = "www.linuxea.com"

如下:

package main
import "fmt"
var version string = "www.linuxea.com"
func main(){
    var me string
    me = "linuxea.com"
    fmt.Println(me)
}

函数外的变量没有使用是不会报错的。

[root@LinuxEA /opt/Golang]# go run 02.go 
linuxea.com

定义多个变量#

通常在定义变量的时候,使用var,每次定义一个。

var name string
var age string

其实我们可以使用逗号将同一个类型的变量隔开进行定义

var name,age string

而对多个变量赋值的时候,也可以如此

name,age = "mark","18"

如下:

package main
import "fmt"
var version string = "www.linuxea.com"
func main(){
    var me string
    me = "linuxea.com"
    fmt.Println(me)

    var name,age string
    name,age = "mark","18"
    fmt.Println(name,age)
}

运行:

[root@LinuxEA /opt/Golang]# go run 02.go 
linuxea.com
mark 18

当然了,也可以把不同类型的变量在一起定义,使用括号即可

我们可以使用var括号进行定义,比如定义一个tel是int类型的,和一个desc是string类型的,如下:

    var (
        tel int
        desc string
    )

赋值

    tel,desc = 10086,"联通"
    fmt.Println(tel,desc)

运行

[root@LinuxEA /opt/Golang]# go run 02.go 
linuxea.com
mark 18
10086 联通

当然了, 我们也可以在声明的时候进行赋值,如下:

    var (
        tel int = 10086
        desc string = "上海"
    )
    fmt.Println(tel,desc)

运行结果仍然不变

[root@LinuxEA /opt/Golang]# go run 02.go 
linuxea.com
mark 18
10086 上海

简短声明#

然而,在定义变量的时候,可以不指定类型,go会根据赋值类型自动推导,但是必须赋值,如下:

!!! note

使用`:=`冒号等于做简短赋值,左边是变量名,右边是值
tel,desc := 10010,"上海市淞虹路"
fmt.Println(tel,desc)

运行

[root@LinuxEA /opt/Golang]# go run 02.go 
10010 上海市淞虹路

var与简短声明的区别#

!!! note

> 注意:这里使用了简短声明,没有使用var声明 。在函数体内可以使用简短声明。而在函数体外必须使用var 定义,如下,go会根据值类型进行自动推导类型
package main
var tel,desc = 10010,"上海市淞虹路"
func main(){}  // 函数体

package main
var (
        tel int = 10086
        desc string = "上海"
    )
    func main(){}   // 函数体

重复赋值#

!!! note

> !注意:变量只能声明一次,不能重复定义,但是可以重复赋值
    tel := 10086
    desc := "上海"

重复赋值,重复赋值只需要等号即可

    tel = 10010
    desc = "北京"

运行结果是最近的赋值结果

[root@LinuxEA /opt/Golang]# go run 03.go 
10010 北京

值交换#

当一次定义了多个值的时候就可以进行交换,这个方式很简单,如下:

    tel,desc := "10010","上海"
    fmt.Println(tel,desc)
    tel,desc = desc,tel
    fmt.Println(tel,desc)
package main
import "fmt"
var version string = "www.linuxea.com"
func main(){
    tel,desc := "10010","上海"
    fmt.Println(tel,desc)
    tel,desc = desc,tel
    fmt.Println(tel,desc)
}

运行

[root@LinuxEA /opt/Golang]# go run 03.go 
10010 上海
上海 10010

!!! note

> 注意:这里交换的值必须是同类型。

4.常量#

常量和变量不同,变量是可以赋值进行修改的,而常量是不能修改的。在使用中有一些值是我们不希望更改的,就可以声明成常量。通常,我们习惯与将常量写为大写。

定义一个常量#

常量可以定义在函数体内和函数体外

    const name string = "mark"
    fmt.Println(name)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
mark

如果进行赋值修改就会报错

# command-line-arguments
./04.go:6:7: cannot assign to name

省略类型#

    const PP = 32132.21
    fmt.Println(PP)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
32132.21

定义多个类型相同的常量#

    const P1,P2 int  = 3,4
    fmt.Println(P1,P2)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
3 4

定义多个类型不相同的常量#

    const (
        P1 string = "mark"
        P2 int  = 4
    )
    fmt.Println(P1,P2)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
mark 4

定义多个常量省略类型#

    const (
        P1  = "mark"
        P2  = 4
        P3 = 32.1
    )
    fmt.Println(P1,P2,P3)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
mark 4 32.1

赋值省略#

在go中,如果产量的第一个值和最后一个值都是一样的,就可以省略掉。如下:

const (
    P1  = 1
    P2
    P3
)
fmt.Println(P1,P2,P3)   

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
1 1 1

还可以像这样

const (
    P1  = "mark"
    P2
    P3
    P100 = 3.5
    P101
    C11 = 123
    C12
)
fmt.Println(P1,P2,P3,P100,P101,C11,C12)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
mark mark mark 3.5 3.5 123 123

枚举#

这种方式可以应用在枚举上,const+iota

枚举是以const()括号内部开始和结束的。不影响到括号外的操作。

const (
    B1 int = iota
    B2
    B3
    B4
)
fmt.Println(B1,B2,B3,B4)

运行

[root@LinuxEA /opt/Golang]# go run 04.go 
0 1 2 3

5.作用域#

作用于定义标识符可以使用的范围。在go中使用{}定义作用域的范围。在{}中可以嵌套语句块。

但是,子语句快可以使用父语句块,父语句快不可以使用子语句块。如下所示就会报:undefined: inner.因为在{}外是不能调用{}内的inner := 2

    outer := 1
    {
        inner := 2
        fmt.Println(outer)
        fmt.Println(inner)
    }
    fmt.Println(inner)

子语句快可以使用父语句块

outer := 1
{
    inner := 2
    fmt.Println(outer)
    fmt.Println(inner)
    {
        inner2 := 3
        fmt.Println(outer,inner,inner2)
    }
}
//fmt.Println(inner)

运行

[root@LinuxEA /opt/Golang]# go run 05.go 
1
2
1 2 3

假如在语句块中嵌套了很多层,那么调用的流程就是就近调用。

outer := 1
{
    inner := 2
    outer := 11
    fmt.Println(outer)
    fmt.Println(inner)
    {
        inner2 := 3
        fmt.Println(outer,inner,inner2)
    }
}
fmt.Println(outer)

运行

[root@LinuxEA /opt/Golang]# go run 05.go 
11
2
11 2 3
1

6.fmt与占位符#

fmt.Println("打印") 打印的同时还会进行换行,而fmt.Print("打印") 是不会换行的。另外fmt.Printf()可以打印变量的类型:

a := "linuxea"
fmt.Printf("%T,%s,%d\n",a,"linuxea",1)
[root@LinuxEA /opt/Golang]# go run 05.go 
string,linuxea,1

有时候会出现%!s之类的,就说明占位符不匹配。需要使用对应的类型

占位符     说明                           举例                   输出
%v      相应值的默认格式。            Printf("%v", people)   {zhangsan},
%+v     打印结构体时,会添加字段名     Printf("%+v", people)  {Name:zhangsan}
%#v     相应值的Go语法表示            Printf("#v", people)   main.Human{Name:"zhangsan"}
%T      相应值的类型的Go语法表示       Printf("%T", people)   main.Human
%%      字面上的百分号,并非值的占位符  Printf("%%")            %
占位符       说明                举例                     输出
%t          true 或 false。     Printf("%t", true)       true
占位符     说明                                  举例                       输出
%b      二进制表示                             Printf("%b", 5)             101
%c      相应Unicode码点所表示的字符              Printf("%c", 0x4E2D)        中
%d      十进制表示                             Printf("%d", 0x12)          18
%o      八进制表示                             Printf("%d", 10)            12
%q      单引号围绕的字符字面值,由Go语法安全地转义 Printf("%q", 0x4E2D)        '中'
%x      十六进制表示,字母形式为小写 a-f         Printf("%x", 13)             d
%X      十六进制表示,字母形式为大写 A-F         Printf("%x", 13)             D
%U      Unicode格式:U+1234,等同于 "U+%04X"   Printf("%U", 0x4E2D)         U+4E2D
占位符     说明                              举例            输出
%b      无小数部分的,指数为二的幂的科学计数法,
        与 strconv.FormatFloat 的 'b' 转换格式一致。例如 -123456p-78
%e      科学计数法,例如 -1234.456e+78        Printf("%e", 10.2)     1.020000e+01
%E      科学计数法,例如 -1234.456E+78        Printf("%e", 10.2)     1.020000E+01
%f      有小数点而无指数,例如 123.456        Printf("%f", 10.2)     10.200000
%g      根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出 Printf("%g", 10.20)   10.2
%G      根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出 Printf("%G", 10.20+2i) (10.2+2i)
占位符     说明                              举例                           输出
%s      输出字符串表示(string类型或[]byte)   Printf("%s", []byte("Go语言"))  Go语言
%q      双引号围绕的字符串,由Go语法安全地转义  Printf("%q", "Go语言")         "Go语言"
%x      十六进制,小写字母,每字节两个字符      Printf("%x", "golang")         676f6c616e67
%X      十六进制,大写字母,每字节两个字符      Printf("%X", "golang")         676F6C616E67
占位符         说明                      举例                             输出
%p      十六进制表示,前缀 0x          Printf("%p", &people)             0x4f57f0
占位符      说明                             举例          输出
+      总打印数值的正负号;对于%q(%+q)保证只输出ASCII编码的字符。 
                                           Printf("%+q", "中文")  "\u4e2d\u6587"
-      在右侧而非左侧填充空格(左对齐该区域)
#      备用格式:为八进制添加前导 0(%#o)      Printf("%#U", '中')      U+4E2D
       为十六进制添加前导 0x(%#x)或 0X(%#X),为 %p(%#p)去掉前导 0x;
       如果可能的话,%q(%#q)会打印原始 (即反引号围绕的)字符串;
       如果是可打印字符,%U(%#U)会写出该字符的
       Unicode 编码形式(如字符 x 会被打印成 U+0078 'x')。
' '    (空格)为数值中省略的正负号留出空白(% d);
       以十六进制(% x, % X)打印字符串或切片时,在字节之间用空格隔开
0      填充前导的0而非空格;对于数字,这会将填充移到正负号之后

占位填充%5d,占位5位,%05d占位5位,缺省的用0填充

    age = 17
    fmt.Printf("%5d\n",age)     //   17
    fmt.Printf("%05d\n",age)    //00017

运行

[root@LinuxEA /opt/Golang]# go run int.go 
   17
00017

默认是右对齐,如果是%-5d,就变成了右对齐

fmt.Printf("%-5d\n",age)
fmt.Printf("%05d\n",age)

运行

[root@LinuxEA /opt/Golang]# go run int.go 
17   
00017

7.布尔类型#

布尔类型用于表示真假,类型名为bool,只有两个值,分别是true和false。0值默认是false

package main
import "fmt"
func main(){

    var hhlo bool
    helo := true
    hell := false
    fmt.Println(hhlo,helo,hell)
}

运行

[root@LinuxEA /opt/Golang]# go run bool.go 
false true false

true表示真,false表示假,零值为false,字面量也是true/false

布尔操作#

逻辑运算有三个,与,或,非与&&或||非!

与:abool && bbool,当两个都为true的时候,结果为true。如果有一个结果为false就不是true.

或:abool || bbool,只要有一个为true的时候,结果就为true。

非:!true,取反。!true非true,也就是false;!false非false,也就是true;可以是字面量,也可以是变量。

关系运算的结果也是true和false. (==,!=),等于和不等于。

    helo := true
    hell := false
    fmt.Println(helo != hell)       // true
    fmt.Println(helo == hell)       // false

8.数值类型#

整型,go提供了5种有符号,5种无符号,1种指针,1种单字节,一种单个unicode字符(unicode码点),共13种整数类型,零值均为0.

标识符:int,uint,rune,int8,int16,int32,int64,uint8,uint16,uint32,uint64,byte,uintptr,其中最为常用的是int类型,rune是单个unicode字符(unicode码点),int8表示8位的Int类型,int16表示int 16位等等。u开头的是无符号,uint8是无符号int8位,uint16是无符号int16位等等。byte一个字节,八位。uintptr是指针类型,与系统有关。

有符号的,0表示正数,1表示负数。表示范围8字节是2^7-2^7-1;无符号表示正数,表示范围是0-2^8-1是256.

package main
import "fmt"
func main(){
    var age int = 18
    fmt.Printf("%T %d",age,age) // int 18
}

打印类型和数值%T%dfmt.Printf("%T %d",age,age)

算数运算#

除数不能为0

    fmt.Println(9 - 5)  //4
    fmt.Println(3 * 3)  //9
    fmt.Println(3 + 3)  //6
    fmt.Println(9 / 2)  //4
    fmt.Println(9 % 2)  //1

自增和自减#

++加1,-- 减1

package main
import "fmt"
func main(){
    var age int = 18
    age = 18
    age++
    fmt.Printf("age++:%d\n",age)
    age--
    fmt.Printf("age--:%d\n",age)
}

运行

[root@LinuxEA /opt/Golang]# go run int.go 
age++:19
age--:18

关系运算#

==等于,!=不等于,>大于,>=大于等于,<小于,<=小于等于

package main
import "fmt"
func main(){
    fmt.Println(1 == 1)
    fmt.Println(2 != 1)
    fmt.Println(2 > 3)
    fmt.Println(2 >= 3)
    fmt.Println(2 < 3)
    fmt.Println(2 <= 3)
}

运行结果

true
true
false
false
true
true

位运算#

位运算实际上是对二进制进行计算,10进制需要转换成二进制进行计算

&与 ,|或 ,^亦或, <<左移,>>右移,&^按位清空

    fmt.Println(7 & 2)      // 2
    fmt.Println(7 | 2)      // 7
    fmt.Println(7 ^ 2)      // 5
    fmt.Println(7 << 2)     // 28
    fmt.Println(7 >> 2)     // 1
    fmt.Println(7 &^ 2)     // 5

这里使用了辗转相除法也可以运算。

赋值运算#

赋值同时可以进行计算,如,=,+=,-=,*=,/=,%=,&=,|=,<<=,>>==,&^=

a+b 等于 a = a+b

    age = 1
    age += 3
    fmt.Println(age)        // 1+3=4

    age -= 2
    fmt.Println(age)        // 4-2=2    

类型转换#

如果两个不同的类型进行运算的时候就需要进行强转换。如果不进行转换就会出错

    var int1 int = 10
    var int2 uint = 2
    fmt.Println(int1 + int2)

当运行时候会抛出错误

[root@LinuxEA /opt/Golang]# go run int.go 
# command-line-arguments
./int.go:44:19: invalid operation: int1 + int2 (mismatched types int and uint)

这时候必须将两个变量的类型转换一致,且不管是int或者uint,只要一致即可。如下:

    var int1 int = 10
    var int2 uint = 2
    fmt.Println(int1 + int(int2))       // int2的uint转换成int
    fmt.Println(uint(int1) + int2)      // int1的int转换成uint
    fmt.Printf("%T %T",int1,int2)       // int uint

运行

[root@LinuxEA /opt/Golang]# go run int.go 
12
12
int uint

我们需要注意的是,当一个int32转换成int8的时候,可能会出现溢出。或者如下的16进制转换:

    var int3 int = 0XFFFF
    fmt.Println(int3)               // 65535
    fmt.Println(uint8(int3))        // 255
    fmt.Println(int8(int3))         // -1
    fmt.Printf("%T",int3)           // int

从大向小转换的时候就可能会出现溢出的问题。

字节与码点#

byte是字节,rune表示码点。这两个在赋值的时候可以使用单引号,而int也可以实现,不过int使用的是十进制。当然,byte和rune也是int类型

    var a byte = 'A'
    var b rune = '测'
    fmt.Println(a,b)        // 65 27979
    fmt.Printf("%T %T",a,b) // uint8 int32

对于码点的打印使用%U,使用%q打印字面量的值

fmt.Printf("%q %q",a,b)     // 'A' U+6D4B

这里可以做个简单的转换,二进制使用%b,八进制%o,十六进制%x

age = 17
fmt.Printf("%T %d %b %o %x\n",age,age,age,age,age)      // int 17 10001 21 11

9.浮点数#

在go中浮点有两种类型,一种是float64,一种是float32。一般使用float64即可

定义与赋值#

默认是0值

package main
import "fmt"
func main(){
    var floatt float64
    fmt.Println(floatt)
}

运行

[root@LinuxEA /opt/Golang]# go run float.go 
0
    var floatt float64
    floatt = 1.666
package main
import "fmt"
func main(){
    var floatt float64
    floatt = 1.666
    fmt.Printf("%T %f",floatt,floatt)
}

运行

[root@LinuxEA /opt/Golang]# go run float.go
float64 1.666000

字面量#

字面量 也分为十进制表示法和科学技术表述法

如:1.666 ,2.666

floatt = 1.666

如:

floatt = 12.02E1

这需要换算

算数运算#

+,-,*,/,++,--。在float中通常不进行自增和自减,而且也不支持(%)余运算

fmt.Println(1.11 + 1.2)
fmt.Println(1.11 - 1.2)
fmt.Println(1.11 * 1.2)
fmt.Println(1.11 / 1.2)

运行结果

[root@LinuxEA /opt/Golang]# go run float.go
2.31
-0.09
1.332
0.925

与整数一样,被除数的不能为0 - 自增和自减

floatt = 1.063
floatt++
fmt.Println(floatt)
floatt--
fmt.Println(floatt)

运行结果

[root@LinuxEA /opt/Golang]# go run float.go
2.0629999999999997
1.0629999999999997

!!! note

> 浮点数不是精确存储,在加减过程中会有一定的精度损耗。
> 如上述中的 1.063在运算后精度损耗会变大,打印时候是1.0629999999999997

关系运算#

由于有精度损耗,对于浮点数来说,不计算等于和不等于。 一般来讲之计算大于>,大于等于>=,小于<,小于等于<=,或者约等于~=

fmt.Println(1.11 > 1.2)
fmt.Println(1.11 >= 1.2)
fmt.Println(1.11 < 1.2)
fmt.Println(1.11 <= 1.2)

运行结果

[root@LinuxEA /opt/Golang]# go run float.go
false
false
true
true

判断浮点数是否等于,可以先进行相减,而后在做比较区间值。如下:

最终的判断取决于精确到的位数

fmt.Println(1.11 - 1.2 <= 0.005)

运行结果

[root@LinuxEA /opt/Golang]# go run float.go
true

浮点数是没有位运算的,直接看赋值运算

赋值运算#

等于=,加等于+=,减等于-=,乘等于*=,除等于/=

    floatt = 1.063
    floatt += 2.25
    fmt.Println(floatt)
    floatt -= 2.25
    fmt.Println(floatt)
    floatt *= 2
    fmt.Println(floatt)
    floatt /= 2
    fmt.Println(floatt)

运行结果

[root@LinuxEA /opt/Golang]# go run float.go
3.3129999999999997
1.0629999999999997
2.1259999999999994
1.0629999999999997

类型转换#

我们知道,默认的是float64。现在转到float32。float32(zsh) 转换到float32

zsh := 1.16389366
fmt.Printf("%T %T\n",zsh,float32(zsh))
fmt.Println(zsh,float32(zsh))

运行

[root@LinuxEA /opt/Golang]# go run float.go
float64 float32
1.16389366 1.1638937

!!! Warning

>如果数据太大,转换后会进行截断

保留数#

比如,现在我要保留五位,并且包含3个小数点-%5.3f。如下:

如果小数点和位数不满足,将用空格替代

fmt.Printf("%5.3f\n",zsh)

运行

[root@LinuxEA /opt/Golang]# go run float.go 
1.164

complex复数#

Go提供了两种大小的复数类型:complex64和complex128,分别由float32和float64组成。内置函数complex从指定的实部和虚部构建复数,内置函数real和imag用来获取复数的实部和虚部:

如果一个浮点数的字面量后面跟着一个i,例如2i,那么它将变成一个复数的虚部,这个复数的实部是0:

    ii := 1 + 2i
    fmt.Printf("%T %v",ii,ii)

运行

[root@marksugar /opt/Golang]# go run float.go 
complex128 (1+2i)

complex128是指实部和虚部都使用的是float64

10.字符串#

定义字符串#

我们在定义字符串的时候,使用双引号和反引号来赋值

    var name string = "mark"
    var desc string = `我是字符串`
    fmt.Println(name,desc)

双引号是可解释的字符串,反引号是原生字符串

[root@marksugar /opt/Golang]# go run string.go 
mark 我是字符串

在字符串中有一些特殊字符,如:\n,\f,\t,\r,\b,\v

    var name string = "ma\trk"
    var desc string = `我是\t字符串`
    fmt.Println(name,desc)

这里的\t是一个tab,也就是4个空格

[root@marksugar /opt/Golang]# go run string.go 
ma  rk 我是\t字符串

算数运算#

可以使用+进行字符串的链接

    var name string = "mark"
    var desc string = `是字符串`
    fmt.Println(name+desc)

运行

[root@marksugar /opt/Golang]# go run string.go 
mark是字符串

关系运算#

关系运算分为:==,!=,>,>=,<,<=

    fmt.Println("a" == "b")  是否等于
    fmt.Println("a" != "b")  是否不等于
    fmt.Println("a" < "b")   是否小于
    fmt.Println("a" > "b")   是否大于
    fmt.Println("aa" <= "b")  是否小于等于
    fmt.Println("a" >= "bb")  是否大于等于

运算大小比较是根据ASCII 码,从左到右进行比较:

[root@marksugar /opt/Golang]# go run string.go 
false
true
true
false
true
false

赋值运算#

    s := "my name is "
    s += "mark"
    fmt.Println(s)

运算

[root@marksugar /opt/Golang]# go run string.go 
my name is mark

索引#

索引计算是0-n-1,n是字符串长度.

    desc = "abcdefg"
    fmt.Printf("%T %c\n",desc[0],desc[0])

desc[0],0对应a,从左到右,索引类型是uint8,这里打印使用的是%c 运行

[root@marksugar /opt/Golang]# go run string.go 
uint8 a

切片#

字符串定义内容必须是ascii

切片是从哪里到哪里,比如:从1到3--desc = "abcdefg",从左到右,1到3则是bc,切片类型string,这里打印使用的是%s

  fmt.Printf("%T %s\n",desc[start:end],desc[start:end])

end不能超过字符串的长度

fmt.Printf("%T %s\n",desc[1:3],desc[1:3])

运行

[root@marksugar /opt/Golang]# go run string.go 
string bc

!!! 字符串定义内容必须是ascii是因为在切片或者索引的时候会出现乱码,特别是在中文字符的时候。如下:

    desc = "我我我"
    fmt.Printf("%T %c\n",desc[0],desc[0])
    fmt.Printf("%T %s\n",desc[1:3],desc[1:3])

运行:

[root@marksugar /opt/Golang]# go run string.go 
uint8 æ
string  

字符串长度#

字符串长度也需要是ascii码,才能精准计算,而中文字符可能使用到三到四个字节。

    desc = "abcdefg"
    fmt.Println(len(desc))

    desc = "我我我"
    fmt.Println(len(desc))

运行

[root@marksugar /opt/Golang]# go run string.go 
7
9

所以这里desc = "我我我"len计算是9。而中文字符串有其他方式。

去掉最后一位#

如果你要取最后一位则是len(desc)-1)

    desc = "abcdefg"
    fmt.Println("desc:",len(desc))
    fmt.Println("desc:",len(desc)-1)

如下:

[root@marksugar /opt/Golang]# go run string.go 
desc: 7
desc: 6

11.指针#

认识指针#

通常变量存储在内存空间,如下图

A存储在2,而后赋值B=A

zhizhen0824

此刻,设置B赋值3,那么赋值是否对A有影响

package main
import "fmt"
func main(){
    A := 2
    B := A
    B = 3
    fmt.Printf("A:%d B:%d",A,B)
}

运行

[root@marksugar /opt/Golang]# go run zhizhen.go
A:2 B:3

上述A是2,B是3,说明赋值给B的3是没有影响到A的值,B是单独的一个值,如下:

zhizhen08241

如果我一定要通过赋值修改A的值,就可以使用指针来进行修改。

如上述中。假如,A赋值的2存储在内存中的地址编号是0DSA6W3,此刻要修改就需要使用A存储的的内存地址进行修改。如下:

zhizhen08242

定义指针#

使用&符号取变量地址,而这个类型也是*int,这个类型就是指针类型。

!!! 如果是一个字符串就是*string,如果是bool就是*bool,如果是浮点数就是*float64.

我们定义一个C的指针

var C *int

简短声明

    A := 2
    B := A
    B = 3
    fmt.Printf("A:%d B:%d\n",A,B)

    C := &A
    fmt.Printf("%T",C)

运行

[root@marksugar /opt/Golang]# go run zhizhen.go 
A:2 B:3
*int

获取指针值#

如果要获取指针的值就需要使用*变量。如:\*c

A := 2
C := &A
fmt.Printf("%T %p",C,*C)
[root@marksugar /opt/Golang]# go run zhizhen.go 
A:2 B:3
*int 2

修改指针值#

    A := 2
    C := &A
    *C = 666
    fmt.Print(*C)
[root@marksugar /opt/Golang]# go run zhizhen.go
666

golang中的指针没有复杂的运算,相对来讲是安全的。

指针的应用#

使用指针

package main
import "fmt"
func main(){
    var name string
    var age int
    var height float64
    fmt.Print("请输入你的名字: ")
    fmt.Scan(&name)
    fmt.Print("请输入你的年龄: ")
    fmt.Scan(&age)
    fmt.Print("请输入你的身高: ")
    fmt.Scan(&height)
    fmt.Printf("你输入的是名字是: [%s]\n输入的年龄是: [%d]\n输入的身高是: [%f]",name,age,height)
}

运行后输入:

[root@marksugar /opt/Golang]# go run zhizhen2.go 
请输入你的名字: mark
请输入你的年龄: 18
请输入你的身高: 1.7
你输入的是名字是: [mark]
输入的年龄是: [18]
输入的身高是: [1.700000]

现在你必须按照类型输入。

!!! Warning

指针的空值是nil