数据的三种基础类型:bool,数字,string 以及定义常量
布尔值:bool
- bool 类型表示一个布尔值,值为 true 或者 false。
- 与运算 &&:
- 当两边都为true时,结果才为true
- 示例:
package main import "fmt" func main() { a := true b := false fmt.Println("a:", a, "b:", b) c := a && b fmt.Println("c:", c) } // 打印:a:true b:false // 打印:c: false
- 或运算 ||
- 当两边有一个为true,结果便为true
- 示例:
package main import "fmt" func main() { a := true b := false fmt.Println("a:", a, "b:", b) d := a || b fmt.Println("d:", d) }
// 打印:a:true b:false // 打印:c: true
数字类型
- 有符号整型:
- int8:表示 8 位有符号整型
- 大小:8 位
- 范围:-128~127
- int16:表示 16 位有符号整型
- 大小:16 位
- 范围:-32768~32767
- int32:表示 32 位有符号整型
- 大小:32 位
- 范围:-2147483648~2147483647
- int64:表示 64 位有符号整型
- 大小:64 位
- 范围:-9223372036854775808~9223372036854775807
- int:根据不同的底层平台(Underlying Platform),表示 32 或 64 位整型。除非对整型的大小有特定的需求,否则通常应该使用 int表示整型。
- 大小:在 32 位系统下是 32 位,而在 64 位系统下是 64 位。
- 范围:在 32 位系统下是 -2147483648~2147483647,而在 64 位系统是 -9223372036854775808~9223372036854775807
- 无符号整型:
- uint8:表示 8 位无符号整型
- 大小:8 位
- 范围:0~255
- uint16:表示 16 位无符号整型
- 大小:16 位
- 范围:0~65535
- uint32:表示 32 位无符号整型
- 大小:32 位
- 范围:0~4294967295
- uint64:表示 64 位无符号整型
- 大小:64 位
- 范围:0~18446744073709551615
- uint:根据不同的底层平台,表示 32 或 64 位无符号整型。
- 大小:在 32 位系统下是 32 位,而在 64 位系统下是 64 位。
- 范围:在 32 位系统下是 0~4294967295,而在 64 位系统是 0~18446744073709551615。
- 浮点型:
- float32:32 位浮点数
- float64:64 位浮点数
- 复数类型:
- complex64:实部和虚部都是 float32 类型的的复数。
- complex128:实部和虚部都是 float64 类型的的复数。
- 其他数字类型:
- byte 是 uint8 的别名。
- rune 是 int32 的别名。
- 补充Printf 方法中的 %T (格式说明符)以及 %d(替换数字)
- unsafe.Sizeof() 该函数接收变量并返回它的字节大小; unsafe 包应该小心使用,因为使用 unsafe 包可能会带来可移植性问题
- %T 格式说明符(Format Specifier),可以打印出变量的类型;
- %d 占位符,用来占位数字类型的值;
- 示例:
package main import ( "fmt" "unsafe" ) func main() { var a int = 89 b := 95 fmt.Println("value of a is", a, "and b is", b) fmt.Printf("type of a is %T, size of a is %d", a, unsafe.Sizeof(a)) // a 的类型和大小 fmt.Printf("\ntype of b is %T, size of b is %d", b, unsafe.Sizeof(b)) // b 的类型和大小 } // 打印: // value of a is 89 and b is 95 // type of a is int, size of a is 4 // type of b is int, size of b is 4
字符串:string
- 介绍:
Go 语言中的字符串是一个字节切片。把内容放在双引号""之间,
暂且可以认为一个字符串就是由很多字符组成的。
- 单独获取字符串的每一个字节:
- 由于字符串是一个字节切片,所以我们可以获取字符串的每一个字节。
- len() 返回字符串中字节的数量
- %x 格式限定符用于指定 16 进制编码
- %c 格式限定符用于打印字符串的字符
- 示例:
package main import ( "fmt" ) // 定义函数printBytes; func printBytes(s string) { for i:= 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } } // 定义函数printChars; func printChars(s string) { for i:= 0; i < len(s); i++ { fmt.Printf("%c ",s[i]) } } func main() { name := "Hello World" printBytes(name) fmt.Printf("\n") printChars(name) } // 打印结果: 48 65 6c 6c 6f 20 57 6f 72 6c 64 H e l l o W o r l d
- rune:
- rune是Go语言中的一个内建类型,也是int32的别称,目的是为了解决不同编码格式之间存在的问题;
- rune表示一个代码点,代码点无论占用多少字节,都可以用一个rune来表示,
- 示例:
package main import ( "fmt" ) func printBytes(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } } func printChars(s string) { runes := []rune(s) fmt.Println("runes:", runes) for i := 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) } } func main() { name := "Hello World" printBytes(name) fmt.Printf("\n") printChars(name) fmt.Printf("\n\n") name = "Señor" printBytes(name) fmt.Printf("\n") printChars(name) } // 打印结果: 48 65 6c 6c 6f 20 57 6f 72 6c 64 runes: [72 101 108 108 111 32 87 111 114 108 100] H e l l o W o r l d 53 65 c3 b1 6f 72 runes: [83 101 241 111 114] S e ñ o r
- 字符串的 for range 循环
package main import ( "fmt" ) func printCharsAndBytes(s string) { for index, rune := range s { fmt.Printf("%c starts at byte %d\n", rune, index) } } func main() { name := "Señor" printCharsAndBytes(name) } // 打印结果: S starts at byte 0 e starts at byte 1 ñ starts at byte 2 o starts at byte 4 r starts at byte 5 // 可以看到 ñ 占用了两个字节
- 用字节切片构造字符串
package main import ( "fmt" ) func main() { byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9} str := string(byteSlice) fmt.Println(str) } // 打印结果: Café
- 用 rune 切片构造字符串
package main import ( "fmt" ) func main() { runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072} str := string(runeSlice) fmt.Println(str) }
// 打印结果: Señor
- 字符串的长度:
- utf8 的包中有一个函数:RuneCountInString() 用来获取字符串的长度。这个方法传入一个字符串参数然后返回字符串中的 rune 的数量。
package main import ( "fmt" "unicode/utf8" ) func length(s string) { fmt.Printf("length of %s is %d\n", s, utf8.RuneCountInString(s)) } func main() { word1 := "Señor" length(word1) word2 := "Pets" length(word2) } // 打印结果: length of Señor is 5 length of Pets is 4
- 字符串不可变:
Go 中的字符串和Python 中的字符串一样是不可变的。一旦一个字符串被创建,那么它将无法被修改。
- 错误示例:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func mutate(s string)string { 8 s[0] = 'a'//any valid unicode character within single quote is a rune 9 return s 10 } 11 func main() { 12 h := "hello" 13 fmt.Println(mutate(h)) 14 } 15 16 // 报错信息:cannot assign to s[0]。
- 倘若真的想修改,可以借助 rune, 修改rune切片中的数值来达到对字符串的修改;
package main import ( "fmt" ) func mutate(s []rune) string { s[0] = 'a' return string(s) } func main() { h := "hello" fmt.Println(mutate([]rune(h))) }
类型转换
- Go 有着非常严格的强类型特征。Go 没有自动类型提升或类型转换。
- 类型转换 往往发生在不同类型的数字类型中; 比如:浮点数 和 无符号整数的转换等等;
- 错误示例:
package main import ( "fmt" ) func main() { i := 55 //int j := 67.8 //float64 sum := i + j //不允许 int + float64 fmt.Println(sum) } // 报错:main.go:10: invalid operation: i + j (mismatched types int and float64) // 在 Go 中, i 的类型是 int ,而 j 的类型是 float64 ,把两个不同类型的数相加,Go 不允许这样的操作
- 正确示例:
package main import ( "fmt" ) func main() { i := 55 //int j := 67.8 //float64 sum := i + int(j) //j is converted to int fmt.Println(sum) } // 打印:122
- 不同类型的数据,相互赋值也会报错:
- 示例:
package main import ( "fmt" ) func main() { i := 10 var j float64 = i // 若没有显式转换,该语句会报错 fmt.Println("j", j) } // 报错:cannot use i (type int) as type float64 in assignment
- 不同类型的数据,不能互相转换;
- 示例: string类型的“10” 转换为 int类型的 10
package main import ( "fmt" ) func main() { var num string = "10" fmt.Printf(int(num)) } // 报错:cannot convert num (type string) to type int
常量
- 介绍定义:
在 Go 语言中,术语"常量"用于表示固定的值。比如 5 、-89、 I love Go、67.89 等等。 用关键字 const 来声明
- 常量的性质:
- 当常量初始化后,不能再重新赋值为其他的值;
- 常量的值,在编译时就会被确定,所以不允许函数将返回值赋值给常量;
- 以上两种错误示例:
1 // 错误一: 常量重新赋值: 2 3 package main 4 5 func main() { 6 const a = 55 // 允许 7 a = 89 // 不允许重新赋值 8 } 9 10 11 // 错误二: 函数的返回值赋值给常量: 12 package main 13 14 import ( 15 "fmt" 16 "math" 17 ) 18 19 func main() { 20 fmt.Println("Hello, playground") 21 var a = math.Sqrt(4) // 允许 22 const b = math.Sqrt(4) // 不允许 23 }
- 字符串常量:
- 所有的字符串,都是常量
- 常量可以赋值给 “合适的” 类型,而不需要类型转换;
package main import ( "fmt" ) func main() { const a = "Sam" // 定义的常量本身是没有定义类型的, var name = a // 但是该常量可以直接赋值给 name 默认为 字符串类型 fmt.Printf("type %T value %v", name, name) }
- 布尔值常量:
布尔常量和字符串常量没有什么不同。他们是两个无类型的常量 true
和 false
。
- 数字常量:
- 数字常量 当它们被分配给变量 或者在需要类型的地方使用时,才需要类型;
- 当数字常量赋值给不同的数字类型的变量时,数字常量的类型,会根据变量的类型而变,不过常量本身是没有数据类型的;
package main import ( "fmt" ) func main() { const a = 5 var intVar int = a var int32Var int32 = a var float64Var float64 = a var complex64Var complex64 = a fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var) } // 打印内容: intVar 5 int32Var 5 float64Var 5 complex64Var (5+0i)
- 数字表达式:
- 数字常量可以在表达式中自由混合和匹配;
package main import ( "fmt" ) func main() { const a = 5 const b = 5.9 var c = a / b fmt.Printf("c's type %T value %v", c, c) } // 打印内容:c's type float64 value 0.847457627118644