继Golang学习系列第二天:变量、常量、数据类型和流程语句之后,今天开始学习数据类型之高级类型: 派生类型。
学过java的人都知道,java其实就8种基本类型:byte、short、int、long、float、double、char、boolean,但它有引用数据类型:字符串、数组、集合、类、接口等。
而golang也有这样的划分,基本类型(Golang学习系列第二天已学过)和派生类型(不叫引用类型),派生类型有以下几种:数组类型、切片类型、Map类型、结构体类型(struct)、指针类型(Pointer)、函数类型、接口类型(interface)、Channel 类型。
1. 数组类型
数组是具有相同数据类型的元素序列。 数组在声明中定义了固定的长度,因此不能扩展超过该长度。 数组声明为
var variable_name [SIZE] variable_type
让我们以代码举例如下
package main
import "fmt"
func main() {
var city [5]string
city[0] = "北京"
city[1] = "上海"
city[2] = "广州"
city[3] = "深圳"
city[4] = "濮阳"
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
}
将变量city声明为5个字符串的数组,执行输出
不过也可以在声明数组时设置数组条目,看简洁版
package main
import "fmt"
func main() {
var city = [5]string{ "北京", "上海","广州","深圳","濮阳"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
//简写版
othercity := [5]string{ "北京", "上海","广州", "深圳","濮阳"}
fmt.Printf("%q", othercity)
}
输出结果
甚至,当您传递值时,可以使用省略号来使用隐式长度
package main
import "fmt"
func main() {
var city = [5]string{ "北京", "上海","广州","深圳","濮阳"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
//简写版
othercity := [5]string{ "北京", "上海","广州", "深圳","濮阳"}
fmt.Printf("%q\n", othercity)
//隐士长度
other_city := [...]string{ "北京", "上海","广州", "深圳","濮阳"}
fmt.Printf("%q", other_city)
}
输出结果
以不同方式打印数组
注意我们使用带Printf的fmt包以及如何使用%q“动词”来打印每个引用的元素。
如果我们使用Println或%s动词,我们将得到不同的结果
package main
import "fmt"
func main() {
//不同方式打印数组
other_city := [...]string{ "北京", "上海","广州", "深圳","濮阳"}
fmt.Println("不同方式打印数组")
fmt.Println(other_city)
fmt.Printf("%s\n", other_city)
fmt.Printf("%q", other_city)
}
执行后输出如图
多维数组
您还可以创建多维数组,示例代码:
package main
import "fmt"
func main() {
var multi [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
multi[i][j] = i + j
}
}
fmt.Println("二维数组: ", multi)
}
输出结果
2. 切片Slices类型
切片包装数组可为数据序列提供更通用,更强大和更方便的接口。 除了具有明确维数的项(例如转换矩阵)外,Go中的大多数数组编程都是使用切片而不是简单数组完成的。
切片包含对基础数组的引用,如果您将一个切片分配给另一个,则两个切片都引用同一数组。 如果函数采用slice参数,则对slice的元素所做的更改将对调用者可见,这类似于将指针传递给基础数组。
切片指向值数组,并且还包含长度。 切片可以调整大小,因为它们只是另一个数据结构之上的包装。
例如, []T is a slice with elements of type T 表示[] T是具有T类型元素的切片。
举个小例子
package main
import "fmt"
func main() {
var city = []string{ "北京", "上海","广州","深圳","濮阳"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
}
2.1 切分切片
可以对切片进行切片,以创建一个指向相同数组的新切片值。表达式为
slice[start:end]
表示计算从start到end-1(含)的元素的一部分。
注意:start和end是表示索引的整数。
下面举个小demo
package main
import "fmt"
func main() {
var city = []string{ "北京", "上海","广州","深圳","濮阳","郑洲"}
fmt.Println(city)
fmt.Println(city[1:4])
// missing low index implies 0
fmt.Println(city[:3])
// [2 3 5]
// missing high index implies len(s)
fmt.Println(city[4:])
}
输出结果
2.2 制造切片
除了通过立即传递值(切片文字)来创建切片之外,还可以使用make关键字创建切片。 您创建一个特定长度的空切片,然后填充每个条目。
package main
import "fmt"
func main() {
fmt.Println("准备用make方式创建切片")
cities := make([]string, 3)
cities[0] = "郑洲"
cities[1] = "濮阳"
cities[2] = "安阳"
fmt.Printf("%q", cities)
}
输出结果:
它通过分配清零的数组并返回引用该数组的切片来工作。
2.3 附加到切片
可以通过append方式附加值到切片中
package main
import "fmt"
func main() {
//附加到切片
other_cities := []string{}
other_cities = append(other_cities, "濮阳")
fmt.Println(other_cities)
}
看输出结果
也可以同时附加多个值到切片中,示例代码同时包括两个城市郑洲和濮阳
package main
import "fmt"
func main() {
//附加多值到切片
other_cities := []string{}
other_cities = append(other_cities, "郑洲","濮阳")
fmt.Println(other_cities)
}
输出结果
甚至您还可以使用省略号将切片附加到另一个切片
package main
import "fmt"
func main() {
fmt.Println("准备用make方式创建切片")
cities := make([]string, 3)
cities[0] = "郑洲"
cities[1] = "濮阳"
cities[2] = "安阳"
fmt.Printf("%q\n", cities)
//附加切片到切片
other_cities := []string{"南京"}
other_cities = append(other_cities, cities...)
fmt.Println(other_cities)
}
输出结果
注意: 省略号是该语言的内置功能,这意味着该元素是一个集合。 我们无法将字符串类型([] string)类型的元素附加到字符串切片中,只能附加字符串。 但是,在切片后使用省略号(...),表示要附加切片的每个元素。 因为我们要从另一个片段追加字符串,所以编译器将接受操作,因为类型是匹配的。
您显然无法将[] int类型的切片附加到[] string类型的另一个切片中。
2.4 复制切片
切片也可以复制。 在这里,我们创建一个与other_cities长度相同的空切片copycities,并从other_cities复制到copycities中。