变量有三种声明方式
var i int = 10
var j = 10
name := "zjc"
一些特殊的情况:一次声明多个变量,变量名和值一一对应
var a, sex, b = 1, "man", 7
也可以这样
a, sex, b := 2, "man", 4
函数外声明全局变量
var (
n1 = 1
n2 = 2
n3 = 3
)
var n4 = "n4"
func main() {
fmt.Println("n1 = ", n1, ", n2 = ", n2, "n3 = ", n3, ", n4 = ", n4)
}
Go和其他语言不一样的一点便是:变量声明后必须使用。
const a int = 1
const name = "zjc"
const b = 4 / 2
iota
const (
a = iota
b = iota
c = iota
)
fmt.Println(a, b, c) // 0 1 2
也可以使用_跳过某些值
const (
a1 = iota //0
_ //1
a2 = iota //2
)
基本数据类型:
1、整数类型(int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、byte)
2、浮点类型(float32、float64)
3、复数(complex64、complex128)
复杂数据类型:
指针、数组、结构体、管道、函数、切片、接口、映射
值类型:基本数据类型、数组、结构体。变量直接存储值,通常存储于栈中,函数传参时使用值传递
引用类型:指针、切片、映射、管道、接口等。变量存储的是值的地址,通常存储于堆中,会发生GC,函数传参时使用引用传递。
查看变量类型:%T
a, sex:= 2, "man"
fmt.Printf("a的类型:%T,sex的类型:%T\n", a, sex)
查看变量占用内存大小时,先导入unsafe和fmt包,再调用unsafe.Sizeof函数就行
import (
"fmt"
"unsafe"
)
fmt.Printf("a占用内存大小:%d, sex占用内存大小:%d", unsafe.Sizeof(a), unsafe.Sizeof(sex))
数组是相同数据类型的一组数据的集合,数组一旦定义长度不能修改
,数组可以通过下标来访问元素。
var a1 [2]int
var a2 [3]string
fmt.Printf("a1: %T\n", a1)
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %T\n", a2)
fmt.Printf("a2: %v\n", a2)
var a1 = [3]int{1,2}
fmt.Printf("a1: %v\n", a1)
var a2 = [2]string{"hello", "world"}
fmt.Printf("a2: %v\n", a2)
var a = [...]int{0 : 1, 2 : 2}
var s = [...]string{1 : "tom", 2 :"zjc"}
fmt.Println(a)
fmt.Println(s)
var a1 = [...]int{1,2,3}
fmt.Printf("len(a1): %v\n", len(a1))
fmt.Printf("a1: %v\n", a1)
数组是固定长度,可以容纳相同数据类型的元素的集合。当长度固定时,使用还是带来一些限制,比如:我们申请的长度太大浪费内存,太小又不够用。鉴于上述原因,有了go语言的切片,可以把切片理解为,可变长度的数组
,其实它底层就是使用数组实现的,增加了自动扩容功能。切片(Slice)是一个拥有相同类型元素的可变长度的序列。
声明一个切片和声明一个数组类似,只要不添加长度就可以了
var 名称 []类型
切片是引用类型,可以使用make函数来创建切片,len为数组的长度,也为切片的起始长度
var slice1 [] 类型 = make([]type, len)
也可以简写为
slice1 := make([]类型,len)
也可以指定容量,其中capacity为可选参数
make([]类型,len,capacity)
var s1 []int
var s2 []string
var s3 = make([]int, 2)
切片拥有自己的长度和容量,我们可以通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量
var names = []string{"tom", "zjc"}
var numbers = []int{1,2,3}
fmt.Printf("len(names): %v\n", len(names))
fmt.Printf("cap(names): %v\n", cap(numbers))
fmt.Printf("len(names): %v\n", len(names))
fmt.Printf("cap(names): %v\n", cap(numbers))
var s1 = make([]string, 2, 3)
fmt.Printf("s1: %v\n", s1)
fmt.Printf("len(names): %v\n", len(s1))
fmt.Printf("cap(names): %v\n", cap(s1))
s1 := []int{}
s1 = append(s1, 1)
s1 = append(s1, 2)
s1 = append(s1, 3, 4, 5, 6)//添加多个元素
fmt.Printf("s1: %v\n", s1)
s3 := []int{3,4,5}
s4 := []int{1,2}
s4 = append(s4, s3...)//添加另一个切片
fmt.Printf("s4: %v\n", s4)
s1 := []int{1,2,3,4,5}
fmt.Printf("s1: %v\n", s1)
//删除索引为2的元素
s1 = append(s1[:2], s1[3:]...)
fmt.Printf("s1: %v\n", s1)
s1 := []int{1,2,3}
s2 := s1
s1[0] = 100
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s2)
s3 := make([]int, 3)
copy(s3, s1)
s1[0] = 1
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s3)
go语言字符串字面量
在Go语言中,字符串字面量使用双引号““
或者反引号`
来创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串则多用于书写多行消息,HTML以及正则表达式。
func main() {
var s1 string = "hello1"
var s2 = "hello2"
s3 := "hello3"
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s2)
fmt.Printf("s3: %v\n", s3)
s4 := `
line 1
line 2
line 3
`
fmt.Printf("s4: %v\n", s4)
}
s1 :="tom"
s2 := "20"
msg := s1 + s2
fmt.Printf("msg: %v\n", msg)
str := "hello world"
n := 3
m := 5
fmt.Println(str[n]) //获取字符串索引位置为n的原始字节
fmt.Println(str[n:])//截取字符串索引位置为n到m-1的字符串
fmt.Println(str[n:])//截取字符串索引位置为n到len(s)-1的字符串
fmt.Println(str[:m])//截取字符串索引位置为0到m-1的字符串
不同数据类型之间必须显式类型转换
a1 := 1.2
a2 := int(a1)
fmt.Println("a2 = ", a2)
如果范围大转换成范围小的,可能会发生精度损失,以下是例子:
var i1 int32 = 12
var i2 int8
var i3 int8
i2 = int8(i1) + 127 // 运行时溢出,得不到想要结果
i3 = int(i1) + 128 // 直接溢出,编译错误
fmt.Println("i2 = ", i2)
基本数据类型转string:
n1 := 10
var s0 = fmt.Sprintf("%d", n1)
fmt.Printf("s type:%T, s = %v\n", s0, s0)
b := true
s0 = fmt.Sprintf("%t", b)
fmt.Printf("s type:%T, s = %v\n", s0, s0)
也可以用strconv包中的函数进行转换,用之前先导入strconv包,然后调用函数进行转换。
n1 := 10
s0 := strconv.FormatInt(int64(n1), 10) // 10表示十进制
fmt.Printf("s type:%T, s = %v\n", s0, s0)
a1 := 20.0
s0 = strconv.FormatFloat(a1, 'f', 10, 64) // 'f'表示浮点数类型、10表示精度10位,64表示float64
fmt.Printf("s type:%T, s = %v\n", s0, s0)
Go语言中的指针操作非常简单,只需要记住两个符号:8(取地址)和*(根据地址取值)。
示例
var ip *int
fmt.Printf("ip: %v\n", ip)//nil
fmt.Printf("ip: %T\n", ip)
var i int = 100
ip = &i
fmt.Printf("ip: %v\n", ip)
fmt.Printf("ip: %T\n", ip)
Go语言中的指针指向数组之后并不像C语言那样指向数组的首元素,而是指向数组中的每一个元素
var ptr [size]int
a := [3]int{1,2,3}
var ptr [3]*int
for i := 0; i < len(a); i++ {
ptr[i] = &a[i]
}
fmt.Printf("ptr: %v\n", ptr)
for i := 0; i < len(a); i++ {
fmt.Printf("ptr: %v\n", *ptr[i])
}
这是一种同时获取索引和值或键值的遍历方式
func main() {
s := "zjc123"
for index, value := range s {
fmt.Printf("%d---%c\n", index, value)
}
}