go语言-golang基础-变量、常量、类型
golang基础
1 第一个go基础
基本的语法机构
// 定义包main package main //go源文件开头必须使用package声明代码所属包,包是go代码分发的最基本单位。 import "fmt" //导入程序依赖的标准包fmt //func用于定义函数。main函数是程序入口,若程序需要运行必须声明main函数,main函数无参数也无返回值 func main() { /* 这是一个注释 这里调用fmt包下的Println函数打印内容到控制台 */ fmt.Println("hello world") //调用fmt.Println函数将参数信息打印到控制台上。打印hello world到控制台 }
// 注释有两种格式。
//行注释f
/*
块注释
*/
编译和运行
1. go build: 用于编译&链接程序或包
例子:go build -work -x -o helloworld.exe main.go
2. go run:用于直接运行程序
例子:go run -work -x main.go
go run helloword.go
3. go clean:清除编译文件 4. 常用参数: -x: 打印编译过程执行的命令,并完成编译或运行 -n: 只打印编译过程执行命令 -work:打印编译过程的临时目录 -o: 指定编译结果文件
2. 程序结构
Go 源文件以 package 声明开头,说明源文件所属的包,接着使用 import 导入依赖的包,其 次为包级别的变量、常量、类型和函数的声明和赋值。函数中可定义局部的变量、常量
3. 基本组成元素
1) 标识符:程序中定义的名字。 变量名,常量名字,函数名字,自定义类型,接口,包名
规范:
1.必须满足:组成只能由非空的unicode编码字符串、数字、下划线组成
⚫ var变量名变量类型=值
定义变量并进行初始化,例如:var name string = "silence"
⚫ var 变量名 变量类型
定义变量使用零值进行初始化,例如:var age int
⚫ var变量名=值
定义变量,变量类型通过值类型进行推导
例如: var isBoy = true
⚫ var 变量名1, 变量名2 , ..., 变量名n 变量类型
定义多个相同类型的变量并使用零值进行初始化
例如:var prefix, suffix string
⚫ var变量名1, 变量名2 , ..., 变量名n 变量类型 = 值1, 值2, ..., 值n
定义多个相同类型的变量并使用对应的值进行初始化,例如:var prev, next int = 3, 4
⚫ var变量名1, 变量名2 , ..., 变量名n = 值1, 值2, ..., 值n
定义多个变量并使用对应的值进行初始化,变量的类型使用值类型进行推导,类型可不相同,例如:var name, age = "silence", 30
⚫ 批量定义
var (
变量名1 变量类型1 = 值1 变量名2 变量类型2 = 值2
) 定义多个变量并进行初始化,批量复制中变量类型可省略 例如:
var (
name string = "silence"
age int = 30
)
初始化表达式可以使用字面量、任何表达式、函数
package main import "fmt" func main() { //变量 给数据起一个名字 var msg string = "hello Jordan" fmt.Println(msg) //其他代码 fmt.Println(msg) //其他代码 fmt.Println(msg) //其他代码 fmt.Println(msg) //var变量名 变量类型 = 值 var name string = "Jordan" //定义变量类型并初始化值. //var 变量名 变量类型 var zeroString string //定义变量类型,但不定义初始化值 //var变量名 = 值 var typeString = "Jordan1" // 定义变量省略类型,不能省略初始化值。 通过对应的值类型推导出变量的类型 shortString := "Jordan3" //短声明(必须在函数内包含函数内子块使用,不能在包级别使用)。通过对应的值类型推导出变量的类型 fmt.Println(name, zeroString, typeString, shortString) // 函数内(块定义的变量必须使用) /* var name string = "Jordan" var msg string = "hello world" var desc string */ // 批量定义.定义多个变量并进行初始化,批量复制中变量类型可省略 var ( name string = "Jordan" msg = "hello world" desc string ) /* x:="x" y:="y" */ // var变量名1, 变量名2 , ..., 变量名n = 值1, 值2, ..., 值n。定义多个变量并使用对应的值进行初始化,变量的类型使用值类型进行推导,类型可不相同,例如: var name1, age1 = "silence", 30 //短声明 x, y := "x1", "y1" fmt.Println(name, msg, desc, name1, age1, x, y)
}
5.2 简短声明
在函数内可以通过简短声明语句声明并初始化变量,可通过简短声明同时声明和初始化多个 变量,需要注意操作符左侧的变量至少有一个未定义过
package main import "fmt" func main() { n1, n2 := 12, 123 fmt.Println(n1, n2) n2, n3 := 34, 35 fmt.Println(n2, n3) }
5.3 变量赋值
在Go语法中,变量初始化和变量赋值是两个不同的概念。下面为声明一个变量之后的赋值过程:
var v10 int v10 = 123
Go语言的变量赋值与多数语言一致,但Go语言中提供了C/C++程序员期盼多年的多重赋值功 能,比如下面这个交换i和j变量的语句:
i, j = j, i
例:
package main import "fmt" func main() { n1, n2 := 12, 123 fmt.Println(n1, n2) n1, n2 = n2, n1 fmt.Println(n1, n2) }
5.4 匿名变量
我们在使用传统的强类型语言编程时,经常会出现这种情况,即在调用函数时为了获取一个 值,却因为该函数返回多个值而不得不定义一堆没用的变量。在Go中这种情况可以通过结合使 用多重返回和匿名变量来避免这种丑陋的写法,让代码看起来更加优雅。
假设GetName()函数的定义如下,它返回3个值,分别为firstName、lastName和 nickName:
func GetName() (firstName, lastName, nickName string) { return "May", "Chan", "Chibi Maruko" }
若只想获得nickName,则函数调用语句可以用如下方式编写:
_, _, nickName := GetName()
这种用法可以让代码非常清晰,基本上屏蔽掉了可能混淆代码阅读者视线的内容,从而大幅 降低沟通的复杂度和代码维护的难度。
6 常量在Go语言中,常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。
6.1 常量定义
通过const关键字,你可以给字面常量指定一个友好的名字:
//const常量名类型=值 const Pi float64 = 3.14159265358979323846 //const 常量名 = 值 const zero = 0.0 // 无类型浮点常量 //批量定义 const ( size int64 = 1024 eof = -1 // 无类型整型常量 ) const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值 const a, b, c = 3, 4, "foo" //a=3,b=4,c="foo", 无类型整型和字符串常量
Go的常量定义可以限定常量类型,但不是必需的。如果定义常量时没有指定类型,那么它与字面常量一样,是无类型常量。
常量定义的右值也可以是一个在编译期运算的常量表达式,比如
const mask = 1 << 3
由于常量的赋值是一个编译期行为,所以右值不能出现任何需要运行期才能得出结果的表达
式,比如试图以如下方式定义常量就会导致编译错误:
const Home = os.GetEnv("HOME")
原因很简单,os.GetEnv()只有在运行期才能知道返回结果,在编译期并不能确定,所以无法作为常量定义的右值。
6.2 预定义常量
Go语言预定义了这些常量:true、false和iota。
iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。
从以下的例子可以基本理解iota的用法:
const ( // iota被重设为0 c0 = iota // c0 == 0 c1 = iota // c1 == 1 c2 = iota // c2 == 2 ) const ( a = 1 << iota // a == 1 (iota在每个const开头被重设为0) b = 1 << iota // b == 2 c = 1 << iota // c == 4 ) const ( u = iota * 42 // u == 0 v float64 = iota * 42 // v == 42.0 w = iota * 42 // w == 84 ) const x = iota // x == 0 (因为iota又被重设为0) const y = iota // y == 0 (因为iota又被重设为0)
果两个const的赋值语句的表达式是一样的,那么可以省略后一个赋值表达式。因此,上面的前两个const语句可简写为:
const ( // iota被重设为0 c0 = iota // c0 == 0 c1 // c1 == 1 c2 // c2 == 2 ) const ( a = 1 <<iota // a == 1 (iota在每个const开头被重设为0) b // b == 2 c // c == 4 )
6.3 枚举
枚举指一系列相关的常量,比如下面关于一个星期中每天的定义。通过上一节的例子,我们看到可以用在const后跟一对圆括号的方式定义一组常量,这种定义法在Go语言中通常用于定义枚举值。Go语言并不支持众多其他语言明确支持的enum关键字。
下面是一个常规的枚举表示法,其中定义了一系列整型常量:
const ( Sunday = iota Monday Tuesday Wednesday Thursday Friday Saturday numberOfDays // 这个常量没有导出 )
同Go语言的其他符号(symbol)一样,以大写字母开头的常量在包外可见。
以上例子中numberOfDays为包内私有,其他符号则可被其他包访问。
7 基础数据类型
Go语言内置以下这些基础类型:
- 布尔类型:bool。
- 整型:int8、byte、int16、int、uint、uintptr等。
- 浮点类型:float32、float64。
- 复数类型:complex64、complex128。
- 字符串:string。
- 字符类型:rune。
- 错误类型:error。
此外,Go语言也支持以下这些复合类型:
- 指针(pointer)
- 数组(array)
- 切片(slice)
- 字典(map)
- 通道(chan)
- 结构体(struct)
- 接口(interface)
7.1 布尔类型
Go语言中的布尔类型与其他语言基本一致,关键字也为bool,可赋值为预定义的true和false示例代码如下:
var v1 bool v1 = true v2 := (1 == 2) // v2也会被推导为bool类型
布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。以下的示例是一些错误 的用法,会导致编译错误:
var b bool b=1 // 编译错误 b = bool(1) // 编译错误
以下的用法才是正确的:
var b bool b = (1!=0) // 编译正确 fmt.Println("Result:", b) // 打印结果为Result: true
例:
package main import "fmt" func main() { isGirl := false fmt.Printf("%T,%#v\n", isGirl, isGirl) //操作 //逻辑运算 a, b, c, d := true, true, false, false //与(&&):左操作数和右操作数都为true,结果为true && fmt.Println("a,b:", a && b) // true && true :true fmt.Println("a,c:", a && c) // true && false:false fmt.Println("c,b:", c && b) // false && true :false fmt.Println("c,d:", c && d) // false && false :false //或(||):左操作数和右操作数有一个为true,结果为true || fmt.Println("a,b:", a || b) //true||true: true fmt.Println("a,c:", a || c) // true || false:true fmt.Println("c,b:", c || b) // false || true :true fmt.Println("c,d:", c || d) // false || false :false //非(!) fmt.Println("a:", !a) //true: false fmt.Println("c:", !c) //false: true //关系
// a) 等于(==)
// b) 不等于(!=)
fmt.Println(a == b) //true==true:true fmt.Println(c != b) //false!=true:true fmt.Println(a == c) //true==false:false fmt.Println(a != c) //true != false: true fmt.Printf("%t,%t", a, a) var bbb bool fmt.Println(bbb) }
使用 fmt.Printf 进行格式化参数输出,占位符: %t
7.2 整型
整型是所有编程语言里最基础的数据类型。Go语言提供了5种有符号、5种无符号、1种指针、1种单字节、1种单个unicode字符(unicode码点),共13种整数类型,零值均为0。
类型名 |
字节宽度 |
说明&取值范围 |
int |
与平台有关,32 位 系统4字节,64位 系统8字节 |
有符号整型 |
uint |
与平台有关,32 位 系统4字节,64位 系统8字节 |
无符号整形 |
rune |
4字节 |
Unicode 码点,取值范围同 uint32 |
int8 |
1字节 |
用 8 位表示的有符号整型,取值范围为:[-128, 127] |
int16 |
2字节 |
用 16 位表示的有符号整型,取值范围为: [-32768,32767] |
int32 |
4字节 |
用 32 位表示的有符号整型,取值范围为: [-2147483648,2147483647] |
int64 |
8字节 |
用 64 位表示的有符号整型,取值范围为: [-9223372036854775808,9223372036854775807] |
uint8 |
1字节 |
用 8 位表示的无符号整型,取值范围为:[0,255] |
uint16 |
2字节 |
用 16 位表示的无符号整型,取值范围为:[0, 65535] |
uint32 |
4字节 |
用 32 位表示的无符号整型,取值范围为:[0, 4294967295] |
uint64 |
8字节 |
用 64 位表示的无符号整型,取值范围为:[0, 18446744073709551615] |
byte |
1字节 |
字节类型,取值范围同 uint8 |
uintptr |
与平台有关,32 位 系统4字节,64位 系统8字节 |
指针值的无符号整型 |
1)类型表示
需要注意的是,int和int32在Go语言里被认为是两种不同的类型,编译器也不会帮你自动 做类型转换,比如以下的例子会有编译错误:
var value2 int32 value1 := 64 // value1将会被自动推导为int类型 value2 = value1 // 编译错误
编译错误类似于:
cannot use value1 (type int) as type int32 in assignment。 使用强制类型转换可以解决这个编译错误:
value2 = int32(value1) // 编译通过
类型转换
当然,开发者在做强制类型转换时,Go 不会对自动对数据类型转换,因此左、右操作数类型必须一致或某个字面量,可通过类型名(数据)的语法将数据转换为对应类型。需要注意数据长度被截短而发生的数据精度损失(比如将浮点数强制转为整数)和值溢出(值超过转换的目标类型的值范围时)问题。
2)数值运算
Go语言支持下面的常规整数运算:+、-、*、/和%、++、--。加减乘除就不详细解释了,需要说下的 是,% 和在C语言中一样是求余运算,比如:
5%3 // 结果为:2
3) 比较运算
Go语言支持以下的几种比较运算符:>、<、==、>=、<=和!=。这一点与大多数其他语言相 同,与C语言完全一致。
下面为条件判断语句的例子:
i, j := 1, 2 if i == j { fmt.Println("i and j are equal.") }
两个不同类型的整型数不能直接比较,比如int8类型的数和int类型的数不能直接比较,但各种类型的整型变量都可以直接与字面常量(literal)进行比较,比如:
var i int32 var j int64 i, j = 1, 2 if i == j { // 编译错误 fmt.Println("i and j are equal.") } if i == 1 || j == 2 { // 编译通过 fmt.Println("i and j are equal.") }
4)位运算
位运算符:&、|、^、<<、>>、&^ 对于负整数在计算机中使用补码进行表示,对应正整数二进制表示取反+1 针对左、右移的右操作数必须为无符号整型。
5)占位符
使用 fmt.Printf 进行格式化参数输出,占位符:
-
%b:二进制
-
%c:字符
-
%d:十进制
◼ %+d表示对正整数带+符号
◼ %nd表示最小占位n个宽度且右对齐
◼ %-nd表示最小占位n个宽度且左对齐
◼ %0nd表示最小占位n个宽度且右对齐,空字符使用0填充 -
%o:八进制,%#o带0的前缀
-
%x、%X:十六进制,%#x(%#X)带0x(0X)的前缀
-
%U: Unicode 码点,%#U 带字符的 Unicode 码点
-
%q:带单引号的字符
6)常用包:
- math
- math/rand
例:
package main import "fmt" func main() { // 正数类型 // 标识符:int/int*/uintptr/byte // 字面两:十进制,八进制,十六进制 var age int = 30 fmt.Printf("%T %d\n", age, age) fmt.Println(0777, 0x10) //操作 // 算术运算(+,-,*,/,%,++,--) fmt.Println(1 + 2) fmt.Println(3 - 10) fmt.Println(3 * 4) fmt.Println(9 / 2) fmt.Println(9 % 2) //fmt.Println(9 % 0) age++ fmt.Println(age) age-- fmt.Println(age) //关系运算(== != < <= > >=) fmt.Println(2 == 3) fmt.Println(2 != 3) fmt.Println(2 < 3) fmt.Println(2 <= 3) fmt.Println(2 > 3) fmt.Println(2 >= 3) //位运算 二进制运算 10 =>2 // & | ^ << >> &^ //十进制转成二 进制 //7 => 0111 //2 => 0010 //7&2 => 0111 & 0010 => 0010 =>2 //7|2 => 0111 | 0010 => 0111 =>7 //7 ^2 => 0111 ^ 0010 => 0101 =>5 //2 << 1 => 0010 << 1 => 0100 =>4 //2 >> 1 => 0010 >> 1 => 0001 => 1 // 7 &^2 => 0111 &^ 0010 => 0101=>5 fmt.Println(7 & 2) fmt.Println(7 | 2) fmt.Println(7 ^ 2) fmt.Println(2 << 1) fmt.Println(2 >> 1) fmt.Println(7 &^ 2) //赋值(=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=,&^=) // a+b ==> a=a+b age = 1 age += 3 // age = age+3 fmt.Println(age) //int.uint/byte/rune/int* var intA int = 10 var uintB uint = 3 fmt.Println(intA + int(uintB)) fmt.Println(uint(intA) + uintB) //大--->小,转换可能出现溢出 var intC int = 0XFFFF fmt.Println(intC, uint8(intC), int8(intC)) //fmt.Println //int/uint/int*/uint* //byte,rune var a byte = 'A' var w rune = '中' fmt.Println(a, w) fmt.Printf("%T %d %b %o %x \n", age, age, age, age, age) fmt.Printf("%T %c \n", a, a) fmt.Printf("%T %q %U\n", w, w, w) //fmt.Printf() }
package main import "fmt" func main() { var age int8 = 31 var age1 = 31 fmt.Printf("%T,%#v,%d\n", age, age, age) fmt.Printf("%T,%#v,%d\n", age1, age1, age1) a, b := 5, 2 fmt.Println(a + b) fmt.Println(a - b) fmt.Println(a * b) fmt.Println(a / b) fmt.Println(a % b) a++ b-- fmt.Println(a, b) //关系运算 fmt.Println(a > b) fmt.Println(a < b) fmt.Println(a == b) fmt.Println(a >= b) fmt.Println(a <= b) //仅了解 位运算 var ( i int = 1 i32 int32 = 1 i64 int64 = 1 ) //类型转换,type(value) int32(i) int64(i) int(i64) fmt.Printf("%T\n", i+int(i32)) fmt.Printf("%T\n", i+int(i64)) fmt.Printf("%T\n", i32+int32(i64)) fmt.Printf("%T\n", i64+int64(i)) var ( aaa byte = 'A' aint byte = 64 unicodePoint rune = '中' ) fmt.Println(aaa, aint, unicodePoint) //%d 十进制 //%b 二进制 //%o 八进制 //%x 十六进制 //%U unicode码点 //%q带单引号的字符 fmt.Printf("%d %b %o %x %U %c %c", aaa, 15, 15, 15, unicodePoint, aaa, 65) }
7.3 浮点型
浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。Go语言中的浮点类型 采用IEEE-754标准的表达方式。
1) 浮点数表示
Go语言定义了两个类型float32和float64,其中float32等价于C语言的float类型, float64等价于C语言的double类型。
字面量:
- 十进制表示法:3.1415926
- 科学记数法:1e-5
在Go语言里,定义一个浮点数变量的代码如下:
var fvalue1 float32 fvalue1 = 12 fvalue2 := 12.0 // 如果不加小数点,fvalue2会被推导为整型而不是浮点型
对于以上例子中类型被自动推导的fvalue2,需要注意的是其类型将被自动设为float64, 而不管赋给它的数字是否是用32位长度表示的。因此,对于以上的例子,下面的赋值将导致编译 错误:
fvalue1 = fvalue2
而必须使用这样的强制类型转换:
fvalue1 = float32(fvalue2)
2)常用操作
- 算术运算(+ - * / ++ --)
- 关系运算(> >= < <= ~=)
- 赋值(= += -= *= /=)
package main import "fmt" func main() { // float32,float64 //字面量:十进制表示法,科学计数表示法 // MEN=> M*10^N //1 var height float64 = 1.68 fmt.Printf("%T %f\n", height, height) var weight float64 = 13.05E1 fmt.Println(weight) //操作 //算术运算(+ - * / ++ --) fmt.Println(1.1 + 1.2) fmt.Println(1.1 - 1.2) fmt.Println(1.1 * 1.2) fmt.Println(1.1 / 1.2) height++ fmt.Println(height) height-- fmt.Println(height) //关系运算(> >= < <= ~=)因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等 是不可行的,这可能会导致不稳定的结果。
fmt.Println(1.1 > 1.2) fmt.Println(1.1 < 1.2) fmt.Println(1.1 <= 1.2) fmt.Println(1.1 >= 1.2) fmt.Println(1.2-1.1 <= 0.005) // 赋值(= += -= *= /=) height += 0.05 fmt.Println(height) fmt.Printf("%T,%T\n", 1.1, height) fmt.Printf("%5.2f\n", height) }
3)占位符
使用 fmt.Printf 进行格式化参数输出,占位符:
-
%f、%F:十进制表示法
◼ %n.mf表示最小占n个宽度并且保留m位小数
-
%e、%E:科学记数法表示
-
%g、%G:自动选择最紧凑的表示方法%e(%E)或%f(%F)
4)常用包
- math
- math/rand
7.4 复数类型
Go提供complex64和complex128两种复数类型,针对complex64复数的实部和虚部均使用float32,针对complex128复数的实部和虚部均使用float64
字面量:
十进制表示法:1 + 2i,, i*i = -1, 1 为实部,2 为虚部
常用函数:
complex: 工厂函数,通过两个参数创建一个复数
real:用于获取复数的实部
imag: 用于获取复数的虚部
1)复数表示 复数表示的示例如下:
var value1 complex64 // 由2个float32构成的复数类型 value1 = 3.2 + 12i value2 := 3.2 + 12i // value2是complex128类型 value3 := complex(3.2, 12) // value3结果同 value2
2)实部与虚部
对于一个复数z = complex(x, y),就可以通过Go语言内置函数real(z)获得该复数的实 部,也就是x,通过imag(z)获得该复数的虚部,也就是y。
3)常用包
- math/cmplx
7.5 字符串
Go语言内置了字符串类型,使用 string 表示
1)字面量:
- 可解析字符串:通过双引号(")来创建,不能包含多行,支持特殊字符转义序列
- 原生字符串:通过反引号(`)来创建,可包含多行,不支持特殊字符转义序列
2)特殊字符:
- \\:反斜线
- \':单引号
- \":双引号
- \a:响铃
- \b:退格
- \f:换页
- \n:换行
- \r:回车
- \t:制表符
- \v:垂直制表符
- \ooo:3个8位数字给定的八进制码点的Unicode字符(不能超过\377)
- \uhhhh:4个16位数字给定的十六进制码点的Unicode字符
- \Uhhhhhhhh:8个32位数字给定的十六进制码点的Unicode字符
- \xhh:2个8位数字给定的十六进制码点的Unicode字符
3)常用操作
- a) 字符串连接:+
- b) 关系运算符:>、>=、<、<=、==、!=
- c) 赋值运算符:+=
- d) 索引:s[index],针对只包含ascii字符的字符串
- e) 切片:s[start:end] ,针对只包含 ascii 字符的字符串
例子:
package main import "fmt" func main() { //""=> 可解释 // `` => 原生字符串 // 特殊字符 \r \n \f \t \b \v var name string = "k\tk" var desc string = `我来\t自中国` fmt.Println(name) fmt.Println("k\\tk") fmt.Println(desc) // 操作 // 算术运算符: +(连接) fmt.Println("我叫" + "tt") //关系运算(== != < <= > >=) fmt.Println("ab" == "bb") fmt.Println("ab" != "bb") fmt.Println("ab" < "bb") fmt.Println("ab" > "bb") fmt.Println("ab" <= "bb") fmt.Println("ab" >= "bb") fmt.Println("bb" >= "ba") fmt.Println("bb" >= "b") //赋值 s := "我叫" s += "kk" fmt.Println(s) // 字符串定义内容必须只能为ascii // 索引 0 - n-1 (n 字符串的长度) desc = "abcdef" fmt.Printf("%T %c \n", desc[0], desc[0]) fmt.Println(len(desc)) //切片 fmt.Printf("%T %s \n", desc[0:2], desc[0:2]) desc = "我爱中国" fmt.Printf("%T %s \n", desc[0:2], desc[0:2]) fmt.Println(len(desc)) }
4)常用函数
- a. len:获取字符串长度(针对只包含ascii字符的字符串)
- b. string: 将 byte 或 rune 数组转换为字符串
package main import "fmt" func main() { var msg = "我的名字\n是Jordan" var msgRaw = `我的名字\n是Jordan` fmt.Printf("%T %s\n", msg, msg) fmt.Printf("%T %s\n", msgRaw, msgRaw) //操作 //字符串连接+ fmt.Println(msg + msgRaw) //赋值 = += msg += "----Jordan" fmt.Println(msg) //索引,切片,ascii msg = "abcdefg" fmt.Printf("%T %#v %c\n", msg[0], msg[0], msg[0]) fmt.Println(msg[1:3]) //len fmt.Println(len(msg)) fmt.Println(len(msgRaw)) }
字符串遍历
Go语言支持两种方式遍历字符串。一种是以字节数组的方式遍历:
str := "Hello,世界" n := len(str) for i := 0; i < n; i++ { ch := str[i] // 依据下标取字符串中的字符,类型为byte fmt.Println(i, ch) }
这个例子的输出结果为:
0 72 1 101 2 108 3 108 4 111 5 44 6 32 7 228 8 184 9 150 10 231 11 149 12 140
可以看出,这个字符串长度为13。尽管从直观上来说,这个字符串应该只有9个字符。这是 因为每个中文字符在UTF-8中占3个字节,而不是1个字节。
另一种是以Unicode字符遍历:
str := "Hello,世界" for i, ch := range str { fmt.Println(i, ch) //ch的类型为rune }
输出结果为:
0 72 1 101 2 108 3 108 4 111 5 44 6 32 7 19990 10 30028
以Unicode字符方式遍历时,每个字符的类型是rune(早期的Go语言用int类型表示Unicode 字符),而不是byte。
5)占位符
使用 fmt.Printf 进行格式化参数输出,占位符:
- %s
6)常用包:
- fmt
- strings
- strconv //https://www.cnblogs.com/golove/p/3262925.html
- unicode
- unicode/utf8
- bytes
- regex
7.6 字符类型
字符类型在Go语言中支持两个字符类型,
- 一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值;
- 另一个是rune,代表单个Unicode字符。
关于rune相关的操作,可查阅Go标准库的unicode包。另外unicode/utf8包也提供了UTF8和Unicode之间的转换。
出于简化语言的考虑,Go语言的多数API都假设字符串为UTF-8编码。尽管Unicode字符在标准库中有支持,但实际上较少使用。
7.7 数组
7.8 数组切片
7.9 map