值类型通常是存储在内存栈空间中的键值对,将变量的实际值存储在栈中随取随用,但在赋值或拷贝时产生的是独立的键值对副本,修改新数据旧值不受影响。

类型长度/Byte默认值说明
bool1false
byte10uint8
rune40Unicode Code Point, int32
int, uint4/8032 或 64 位
int8, uint810-128 ~ 127, 0 ~ 255,byte是uint8 的别名
int16, uint1620-32768 ~ 32767, 0 ~ 65535
int32, uint3240-21亿~ 21亿, 0 ~ 42亿,rune是int32 的别名
int64, uint6480
float3240.0
float6480.0
complex648
complex12816
stringUTF-8 字符串
array固定长度的数组

01 布尔类型

booltruefalse

布尔类型有如下特点:

false
func BoolExp() {
	var flag bool
	if !flag {
		fmt.Println("flag is false")
	}
}

02 字符类型

char
bytecharuint8runeint32Unicode
func CharExp() {
	var a byte = 'A'
	var b rune = 'A'

	fmt.Printf("sizeof a is %d bytes\n", unsafe.Sizeof(a))
	fmt.Printf("sizeof b is %d bytes\n", unsafe.Sizeof(b))
}

03 整型

Golang中对数据类型进行更明确的命名,其中国整型分为以下两个大类:

int8int16int32int64uint8uint16uint32uint64
uint8bytecharint16shortint32intint64long
func IntExp() {
	var a int8 = 1
	var b int16 = 1
	var c int32 = 1
	var d int64 = 1
	var e int = 1

	fmt.Printf("size of a is %d bytes", unsafe.Sizeof(a))
	fmt.Printf("size of b is %d bytes", unsafe.Sizeof(b))
	fmt.Printf("size of c is %d bytes", unsafe.Sizeof(c))
	fmt.Printf("size of d is %d bytes", unsafe.Sizeof(d))
	fmt.Printf("size of e is %d bytes", unsafe.Sizeof(e))
}

哪些情况下使用int和uint:

Golang 有根据平台字节长度差异自动匹配特定平台整型长度的类型:int和uint

在使用int和uint类型时,不能假定它是32位或64位的整型,而是考虑int和uint可能在不同平台上的差异。

逻辑对整型范围没有特殊需求。例如,对象的长度使用内建len()函数返回,这个长度可以根据不同平台的字节长度进行变化。实际使用中,切片或map的元素数量等都可以用int来表示。

反之,在二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用int和uint。

04 浮点类型

float32float64floatdouble
float323.4e38math.MaxFloat32float641.8e308math.MaxFloat64

05 复数类型

float32float64complex64complex128
realimag
var a complex128 = complex(1, 2) 
var b complex128 = complex(3, 4) 

fmt.Println(a*b) 
fmt.Println(real(a*b))
fmt.Println(imag(a*b))

06 字符串类型

UTF-8

6.1 定义字符串

string""
func StringExp() {
	var str1 string = "hello, world"
	var str2 = "golang \\"
	str3 := "go"

	fmt.Println(str1, "printed by", str2, str3)
}
\\
转义含义
\r回车符(返回行首)
\n换行符(直接跳到下一行的同列位置)
\t制表符(tab键)
单引号
"双引号
\反斜杠

定义多行字符串:Golang中可以使用反引号定义一个多行字符串,但反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。

func MultiRows() {
	var rows = `hello \n
		world!
		\t golang
	`

	fmt.Println(rows)
}

6.2 字符串操作

方法介绍
len(str)求长度
+ 或 fmt.Sprintf拼接字符串
strings.Split分割
strings.Contains判断是否包含
strings.HasPrefix,strings.HasSuffix前缀/后缀判断
strings.Index(),strings.LastIndex()子串出现的位置
strings.Join(a[]string, sep string)join操作

(1)获取字符串长度

len()RuneCountInString()
len()str1len(str1)str2len(str2)
func StringLen() {
	var str1 string = "hello, world"
	str2 := "你好"

	fmt.Printf("the length of str1 is %d, str2 is %d\n", len(str1), len(str2))
	fmt.Printf("the length of str1 is %d, str2 is %d\n", len(str1), utf8.RuneCountInString(str2))
}
RuneCountInString()

(2)遍历字符串

[]
func StringTraversal() {
	str1 := "hello, world"
	str2 := "hello, 世界"
	for i := 0; i < len(str1); i++ {
		fmt.Printf(" %c:%d", str1[i], str1[i])
	}
	fmt.Println()
	for i := 0; i < len(str2); i++ {
		fmt.Printf(" %c:%d", str2[i], str2[i])
	}
	fmt.Println()
	for _, ch := range str2 {
		fmt.Printf(" %c:%d", ch, ch)
	}
	fmt.Println()
}
str1str2for range
[]byte3~4

(3)截取子字符串

[m:n]str[m,n)
func StringSubStr() {
	str := "hello, 世界"
	fmt.Printf("str[0:5]:%s\n", str[0:5])
	fmt.Printf("str[0:8]:%s\n", str[0:8])
	fmt.Printf("str[0:10]:%s\n", str[0:10])
	fmt.Printf("str[7:]:%s\n", str[7:])
}

(4)拼接字符串

++=
func StringAppend() {
    str1 := "hello, "
    str2 := "world!"
    str := str1 + str2
    fmt.Printf("%s + %s = %s\n", str1, str2, str)
    str += "你好,世界!"
    fmt.Printf("new string: %s\n", str)
}

(5)修改字符串

[]rune[]bytestring
func StringChange() {
	str1 := "hello, world"
	byteStr1 := []byte(str1)
	byteStr1[1] = 'E'
	fmt.Println("change str1: ", string(byteStr1))

	str2 := "hello, 世界"
	runeStr2 := []rune(str2)
	runeStr2[7] = '国'
	fmt.Println("change str2: ", string(runeStr2))
}
strings
//判断两个字符串是否相同,忽略大小写。
func EqualFold(s, t string) bool
//判断字符串p的前缀是否为prefix
func HasPrefix(s, prefix string) bool
//判断字符串的结尾是否为suffix
func HasSuffix(s, suffix string) bool
//判断字符串s是否包含substr
func Contains(s, substr string) bool
//判断字符串中是否包括rune字符
func ContainsRune(s string, r rune) bool
//字符串s中是否包含chars任何一个字符
func ContainsAny(s, chars string) bool
//统计s中有多少sep个字符串
func Count(s, sep string) int
//返回在s中sep的首字母位置
func Index(s, sep string) int
//返回字符c在s中的位置
func IndexByte(s string, c byte) int
//返回字符r在s中的位置
func IndexRune(s string, r rune) int
//返回字符串chars中在s中出现最早的位置
func IndexAny(s, chars string) int
//返回符合函数规范的索引
func IndexFunc(s string, f func(rune) bool) int
//任意的字符chars在s中最后一个字符的索引
func LastIndexAny(s, chars string) int
//转换成小写字母
func ToLower(s string) string
//转换成大写字母
func ToUpper(s string) string
//字符串中的指定字符,最后一个参数为替换的个数,如果为-1,则全部替换
func Replace(s, old, new string, n int) string
//将所有包含sutset的开头和结尾的字符全部删除
func Trim(s string, cutset string) string
//删除全部空白
func TrimSpace(s string) string
//删除根据函数进行字符串开头和结尾的删除
func TrimFunc(s string, f func(rune) bool) string
//将字符串左侧的指定字符删除
func TrimLeft(s string, cutset string) string
//将字符串左侧符合函数的字符进行删除
func TrimLeftFunc(s string, f func(rune) bool) string
//将字符串左侧的prefix进行删除
func TrimPrefix(s, prefix string) string
//按字符串之间的空白进行分割,返回数组
func Fields(s string) []string
//按字符串中符合函数的字符进行分割
func FieldsFunc(s string, f func(rune) bool) []string
//将字符串中的sep作为分割符,进行分割,返回数组
func Split(s, sep string) []string
//按照sep进行分割,并且可以指定分割的次数
func SplitN(s, sep string, n int) []string
//前些个分割字符串是将分割符进行删除,此函数,将在分割符后进行分割。
func SplitAfter(s, sep string) []string
//不删除分割符,并指定分割次数
func SplitAfterN(s, sep string, n int) []string
//将字符串型数组,按照指定连接符进行连接
func Join(a []string, sep string) string

07 定长数组

7.1 定义数组

Golang中数组 Array 是同一种数据类型的固定长度的序列,所以定义数组时必须指定存放元素的类型和容量,其格式如下所示:

var 变量名称 [数组容量]数据类型

// example:
var arr0 [5]int
var arr1 [3]bool

如果在定义数组时不对其进行初始化,则使用默认值填充,整型默认值是0、浮点型默认值是0.0、布尔类型默认值是false、字符串默认值则是空串。

使用大括号初始化数组:即在大括号中定义好和数组指定的数据类型与数组容量一致的值

var arr0 = [5]int{1, 2, 3, 4, 5}
var arr1 [3]bool
fmt.Println("arr0:", arr0, "\narr1:", arr1)
...
var arr2 = [7]int{1, 2, 3, 4, 5, 6, 7}
var arr3 = [7]int{1, 2, 3}
var arr4 = []int{1, 2, 3}
var arr5 = [...]int{1, 2, 3}
fmt.Println("arr2:", arr2, "\narr3:", arr3, "\narr4:", arr4, "\narr5:", arr5)

通过指定索引对应的值初始化数组:在大括号中指定索引对应的值,未指定索引的值会用默认值填充。

arr6 := [5]int{0: 1, 3: 4}
arr7 := []int{0: 1, 4: 5, 8: 9}
fmt.Println("arr6:", arr6, "\narr7:", arr7)

7.2 定义多维数组

Golang中可以通过增加容量维度来定义多维数组,声明语法格式如下所示:

var 变量名称 [一维容量][二维容量]...[N维容量]数据类型

// example:
var arr8 [3][3]int
var arr9 [3][3][3]bool

多维数组的初始化与一维一致,满足嵌套结构

arr8 := [3][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{0: 7, 2: 9},
	}
fmt.Println("arr8:", arr8)

多维数组容量声明时仅能省略第一维度,其他维度不可省略

arr10 := [...][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{0: 7, 2: 9},
	}
arr11 := [][3]int{
		{1, 2, 3},
		{0: 7, 2: 9},
	}
fmt.Println("arr10:", arr10, "\narr11:", arr11)

7.3 遍历数组

len()[]
func ArrayTraversal() {
	var arr0 = [5]int{1, 2, 3, 4, 5}
	for i := 0; i < len(arr0); i++ {
		fmt.Printf("%d:%d ", i, arr0[i])
	}

	arr8 := [3][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{0: 7, 2: 9},
	}
	for i := 0; i < len(arr8); i++ {
		for j := 0; j < len(arr8[0]); j++ {
			fmt.Printf("(%d,%d):%d ", i, j, arr8[i][j])
		}
	}
}
for range
func ArrayTraversal() {
	var arr0 = [5]int{1, 2, 3, 4, 5}
	for _, e := range arr0 {
		fmt.Printf("%d", e)
	}

	arr8 := [3][3]int{
		{1, 2, 3},
		{4, 5, 6},
		{0: 7, 2: 9},
	}
	for k1, row := range arr8 {
		for k2, elem := range row {
			fmt.Printf("(%d,%d):%d ", k1, k2, elem)
		}
	}
}

参考资料