基本类型
Go支持一下几种数据类型
类型称呼 | 类型(Type) | 字面量(Literal) |
---|---|---|
布尔值 | bool | true,false |
整数 | int, int8, uint8, int16, uint16, int32, uint32, int64, uint64 | …-1,0,1… |
浮点数 | float64, float32 | 23.5, 2e-12 |
字节 | byte (uint8, 1个char) | ‘a’ |
符文 | rune (int32, 1个Unicode字符) | ‘b’ |
字符串 | string | “Hello”,‘World’ |
常量 | constants | const a = 8 |
结构体 | structs | type Foo struct {} |
切片 | slice (可变长向量) | []int = {1,-3,4} |
数组 | array (固定长度向量) | [2]int = {2,3} |
映射 | map (其他语言中成为字典dict或哈希表hash table) | map[string]int |
布尔型
布尔类型关键字为bool
,它的取值为true
或false
,未赋值的布尔值为false
,布尔类型的长度为1字节。
布尔基本用法
package main
import (
"fmt"
)
func main() {
var b bool = true
fmt.Printf("b is: '%v'\n", b) // b is: 'true'
b = false
fmt.Printf("b is: '%v'\n", b) // b is: 'false'
var b2 bool
fmt.Printf("zero value of bool is: '%v'\n", b2) // zero value of bool is: 'false'
b := true
fmt.Printf("size of bool is: %d\n", unsafe.Sizeof(b)) // size of bool is: 1
}
整型
有符号和无符号
Go语言有固定长度的有符号和无符号整数类型,默认值为0:
属性值 | 描述 | |
---|---|---|
有符号 | int8 | -128 到 127 |
int16 | -32768 到 32767 | |
int32 | -2147483648 到 2147483647 | |
int64 | -9223372036854775808 到 9223372036854775807 | |
无符号 | uint8/td> | 0 到 255 |
uint16 | 0 到 65535 | |
uint32 | 0 到 4294967295 | |
uint64 | 0 到 18446744073709551615 | |
依赖于CPU架构的整型 | int | 在32为处理器上表示int32,在64位处理器上表示int64 |
uint | 在32位处理器上是uint32,在64位处理器上是uint64 |
实现int
转string
方法一:strconv.Itoa()
package main
import (
"fmt"
"strconv"
)
func main() {
var i1 int = 26
fmt.Printf("i1: %s\n", strconv.Itoa(i1)) // i1: 26
}
方法二:fmt.Sprintf()
package main
import (
"fmt"
)
func main() {
var i1 int = -26
s1 := fmt.Sprintf("%d", i1)
fmt.Printf("i1: %s\n", s1) // i1: -26
}
实现string
转int
方法一:stronv.Atoi()
package main
import (
"fmt"
"log"
"strconv"
)
func main() {
s := "-52"
i1, err := strconv.Atoi(s)
if err != nil {
log.Fatalf("strconv.Atoi() failed with %s\n", err)
}
fmt.Printf("i1: %d\n", i1) // i1: -52
}
方法二:fmt.Sscanf()
package main
import (
"fmt"
"log"
)
func main() {
s := "348"
var i int
_, err := fmt.Sscanf(s, "%d", &i)
if err != nil {
log.Fatalf("fmt.Sscanf failed with '%s'\n", err)
}
fmt.Printf("i1: %d\n", i) // i1: 348
}
浮点数
float32大约可以提供小数点后6位的精度,作为对比,float64可以提供小数点后15位的精度。通常情况应该优先选择float64,因此float32的精确度较低,在累积计算时误差扩散很快,而且float32能精确表达的最小正整数并不大,因为浮点数和整数的底层解释方式完全不同,具体自行搜索IEEE754详解。
类型 | 描述 |
---|---|
float32 | IEEE-754 32位浮点型数 |
float64 | IEEE-754 64位浮点型数 |
complex64 | 32 位实数和虚数 |
complex128 | 64 位实数和虚数 |
浮点数基本用法
// 浮点型的用法
package main
import (
"fmt"
"unsafe"
)
func main() {
// 如果浮点数声明时未指定变量的类型
// 默认为 float64 类型
var n1 = 3.99
fmt.Printf("n1的值为 %g, 类型是 %T, 占 %d 个字节\n", n1, n1, unsafe.Sizeof(n1)) // n1的值为 3.99, 类型是 float64, 占 8 个字节
// 声明为 float32 类型
var n3 float32 = 1.6789
fmt.Printf("n3的值为 %g, 类型是 %T, 占 %d 个字节\n", n3, n3, unsafe.Sizeof(n3)) // n3的值为 1.6789, 类型是 float32, 占 4 个字节
// 在用Printf进行格式化输出时,最好用 %g或%G 进行
// 格式化输出,如果用 %f 的话可能会造成精度丢失导
// 致数据不准确
var f1 float32 = 1.2098
fmt.Println("f1 =", f1) // f1 = 1.2098
fmt.Printf("f1 = %f\n", f1) // f1 = 1.209800
fmt.Printf("f1 = %g\n", f1) // f1 = 1.2098
fmt.Printf("f1 = %G\n", f1) // f1 = 1.2098
fmt.Printf("f1 = %e\n", f1) // f1 = 1.209800e+00
fmt.Printf("f1 = %E\n", f1) // f1 = 1.209800E+00
}
字节和符号
Go有两种字符类型:
byte
是长度为1字节的值,它是uint8类型的别名rune
是长度为4字节的Unicode码位(Code-Point),它是int32的别名
byte
和rune
的默认值是0。
使用byte遍历字符串
package main
import (
"fmt"
"unsafe"
)
func main() {
s := "str"
fmt.Printf("s的数据类型为: %T\n", s) // s的数据类型为: string
for i := 0; i < len(s); i++ {
c := s[i]
fmt.Printf("c的值为 %c, 类型是 %T, 占 %d 个字节, 地址(0x%x)\n", c,c,unsafe.Sizeof(c),c)
//c的值为 s, 类型是 uint8, 占 1 个字节, 地址(0x73)
//c的值为 t, 类型是 uint8, 占 1 个字节, 地址(0x74)
//c的值为 r, 类型是 uint8, 占 1 个字节, 地址(0x72)
}
}
使用rune遍历字符串
package main
import "fmt"
func main() {
s := "中国汉字"
fmt.Printf("s的数据类型为: %T\n", s) // s的数据类型为: string
for i, runeChar := range s {
fmt.Printf("Rune at byte position %d is %#U Type %T\n", i, runeChar,runeChar)
// Rune at byte position 0 is U+4E2D '中' Type int32
// Rune at byte position 3 is U+56FD '国' Type int32
// Rune at byte position 6 is U+6C49 '汉' Type int32
// Rune at byte position 9 is U+5B57 '字' Type int32
}
}
一个字符串本质上是一个字节数组。
当用rune遍历字符串时,编译器会假定待遍历的是用UTF-8编码的Unicode字符串。
UTF-8是一种变长编码方案,被编码的每个字符的长度可能是1,2,3或4字节。这样遍历时,返回的变量i表示每个字符起始字节的位置,而不是字符所在串中第几个位置。
字符串
Go语言中字符串是一个不可变的字节(8-bit byte)序列。
string
的默认值是空字符串""
。
字符串基本用法
package main
import (
"fmt"
)
func main() {
var s string // 空字符串 ""
//用双引号不能换行, 但支持转义如"\n\t..."
s1 := "string\nliteral\nwith\tescape characters\n"
//string用反引号能换行, 但不支持转义
s2 := `raw string literal
which doesnt't recgonize escape characters like \n
`
fmt.Printf("sum of strings\n'%s'\n", s+s1+s2)
//sum of strings
//'string
//literal
//with escape characters
//raw string literal
//which doesnt't recgonize escape characters like \n
//'
}
常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量的声明:
const (
i int = 32 // int constant
s = "string" // string constant
i2 = 33 // untyped number constant
)
var (
// 非只读类型的值(如切片和映射)则不可以声明为常量
// 我们只能把它们声明为变量
b = []byte{3, 4} // 这不是一个常量
)
结构体(struct)
结构体的作用是将多个值聚合为单个实体。
一个struct
的零值是其字段被设为各自的零值
struct
声明方式:
package main
import "fmt"
type Books struct {
name string
age int
sex string
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"小红", 20, "男"}) // {小红 20 男}
// 也可以使用 key => value 格式
fmt.Println(Books{name: "小红", age: 20, sex: "男"}) // {小红 20 男}
// 忽略的字段为 0 或 空
fmt.Println(Books{name: "小红", age: 20}) // {小红 20 }
}
切片
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。