Golang复合类型
简述
基本类型是Go语言世界的原子,复合类型则是分子。
数组
数组是固定长度的序列。因此,其很少直接使用。 与C语言数组特性类似。
var a [3]int //其中[3]int为数组类型
fmt.Println(a[0])
fmt.Println(a[len(a) - 1])
var b [3]int = [3]int{1, 2, 3}
var c [3]int = [3]int{1, 2}
var d = [...]int{1, 2, 3, 4} // len = 4
q := [...]int{1, 2}
//指定一个索引和对应值列表的方式初始化
type Currency int
const (
USD Currency = iota // 美元
EUR // 欧元
GBP // 英镑
RMB // 人民币
)
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}
fmt.Println(RMB, symbol[RMB]) // "3 ¥"
r := [...]{99: -1} //第100个元素初始化为-1
如果两个数组类型可以比较,那么两个数组是可以用==或!=比较
a := [...]int{1, 2}
b := [...]int{1, 2, 3}
c := [...]int{1, 2}
d := [...]int{1, 1}
fmt.Println(a == b) //err: [2]int与[3]int数组类型不同
fmt.Println(a == c) //true
fmt.Println(a == d) //false
数组用于函数参数,由于数组长度的固定性。一般不用于函数参数。
//清零数组
func zero(ptr *[32]byte) {
*ptr = [32]byte{}
}
// zero函数不能接受[16]byte类型的指针
切片(Slice)
- 基本概念
构成: 指针、长度和容量 指针为Slice第一个元素地址,并不一定是数组第一个元素地址 len和cap分别返回长度和容量,len(slice) <= cap(slice)
months := [...]string{1: "January", /* ... */, 12: "December"}
months[1:13] //引用12个月份
months[1:] //引用12个月份
months[:] //引用整个数组,0和12个月份
- Slice作为函数参数
func reverse(s []int) {
for i, j := 0, len(s) - 1; i < j; i++, j-- {
s[i], s[j] = s[j], s[i]
}
}
a := [...]int{1, 2, 3, 4, 5}
reverse(a) //error, must be Slice.
reverse(a[:])
- Slice不能进行==或!=比较
- slice唯一合法的比较操作是和nil比较
var s []int // len(s) == 0, s == nil
s = nil // len(s) == 0, s == nil
s = []int(nil) // len(s) == 0, s == nil
s = []int{} // len(s) == 0, s != nil
- 判断Slice是否为空,需要用len(s) == 0判断
- Slice创建和追加元素
make([]T, len)
make([]T, len, cap) // same as make([]T, cap)[:len]
s := make([]int, 5)
s = append(s, 1)
s = append(s, 2)
fmt.Println(s)
- Slice 追加 Slice
s1 := []int{1, 2, 3, 4}
s2 := []int{5}
s2 = append(s2, s1...)
- 切片插入元素
func insertSlice(s []interface{}, pos int, value interface{}) []interface{} {
rear := append([]interface{}{}, s[pos:]...)
s = append(s[:pos], value)
s = append(s, rear...)
fmt.Printf("addr-s: %p\n", s)
return s
}
Map
与cpp中的unordered_map类似,Go中的map底层也是哈希表 map[K]V中的K必须是支持==运算符的数据类型 符点数用作K是一个糟糕的用法,符点数具有精度问题。
- map创建
//使用make创建
ages := make([string]int)
//字面值创建
ages := map[string]int{
"alice": 31,
"charlie": 34,
}
//创建空map
ages := map[string]int {}
//遍历
for name, age := range ages {
fmt.Printf("%s\t%d\n", name, age)
}
fmt.Println(ages["alice"])
fmt.Println(ages["Lily"]) //不存在的key,返回对应类型的0值
/////nil
var ages map[string]int
fmt.Println(ages == nil) // "true"
fmt.Println(len(ages) == 0) // "true"
//判断key是否存在
age, ok := ages["Lucy"]
if !ok {
//not exists
}
//简写
if age, ok := ages["Lucy"]; !ok {
/////////
}
- map的零值为nil
- map之间不能进行==或!=比较,只能和nil比较
- Map的value类型也可以是一个聚合类型
- 不支持 == 操作的不能作为 map key:如 slice、function、map
结构体
- 相邻成员如果类型相同,可以合并到同一行
type Employee struct {
ID int
Name, Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
- 没有任何成员的结构体是空结构体,表示为struct{}, 其默认零值为struct{}{}
- 结构体字面值
//方法一,较小的结构体中使用
type Point struct {
x, y int
}
p := Point{1, 2}
//方法二,通用型
type T struct {
a, b int
}
t := T{a: 2, b: 3}
- 作为函数参数和返回值
type Point struct {
x, y int
}
func Scale(p Point, factor int) Point {
return Point{p.x * factor, p.y * factor}
}
//对于较大结构体或为了改变成员的值,需要用结构体指针作参数
func Scale(p *Point, factor int) {
p.x *= factor
p.y *= factor
}
- 两个结构体可以用==或!=进行比较
type Point struct {
x, y int
}
p := Point{x: 1, y: 2}
q := Point{x: 2, y: 1}
fmt.Println(p == q) //false
- 匿名成员
匿名成员必须是命名类型或命名类型指针 外层结构体获得匿名成员的所有成员和可导出方法
type Point struct {
x, y int
}
type Circle struct {
Point
Radius int
}
type Wheel struct {
Circle
Spokes int
}
var w Wheel
w.x = 1
w.y = 2
w.Radius = 3
w.Spokes = 5
//字面值表示
w = Wheel{Circle{Point{8, 8}, 5}, 20}
w = Wheel{
Circle: Circle{
Point: Point{X: 8, Y: 8},
Radius: 5,
},
Spokes: 20, // NOTE: trailing comma necessary here (and at Radius)
}
w = Wheel{1, 2, 3, 5} //compile error
JSON
- marshaling(编码): 将结构体Slice转为json字符串的过程
- unmarshaling(解码): 将json字符串转为结构体Slice的过程
type Movie struct {
Title string
Year int `json:"released"`
Color bool `json:"color,omitempty"`
Actors []string
}
var movies = []Movie{
{Title: "Casablanca", Year: 1942, Color: false,
Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},
{Title: "Cool Hand Luke", Year: 1967, Color: true,
Actors: []string{"Paul Newman"}},
{Title: "Bullitt", Year: 1968, Color: true,
Actors: []string{"Steve McQueen", "Jacqueline Bisset"}},
// ...
}
//编码
data, err := json.Marshal(movies) //或MarshalIndent产生缩进json字符串
if err != nil {
log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s\n", data)
//解码
var titles []struct{ Title string } //获取部分json内容
if err := json.Unmarshal(data, &titles); err != nil {
log.Fatalf("JSON unmarshaling failed: %s", err)
}
fmt.Println(titles) // "[{Casablanca} {Cool Hand Luke} {Bullitt}]"
文本和HTML模板
//…