值类型通常是存储在内存栈空间中的键值对,将变量的实际值存储在栈中随取随用,但在赋值或拷贝时产生的是独立的键值对副本,修改新数据旧值不受影响。
类型 | 长度/Byte | 默认值 | 说明 |
---|---|---|---|
bool | 1 | false | |
byte | 1 | 0 | uint8 |
rune | 4 | 0 | Unicode Code Point, int32 |
int, uint | 4/8 | 0 | 32 或 64 位 |
int8, uint8 | 1 | 0 | -128 ~ 127, 0 ~ 255,byte是uint8 的别名 |
int16, uint16 | 2 | 0 | -32768 ~ 32767, 0 ~ 65535 |
int32, uint32 | 4 | 0 | -21亿~ 21亿, 0 ~ 42亿,rune是int32 的别名 |
int64, uint64 | 8 | 0 | |
float32 | 4 | 0.0 | |
float64 | 8 | 0.0 | |
complex64 | 8 | ||
complex128 | 16 | ||
string | UTF-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)
}
}
}