数组
package main
import "fmt"
//指针传递,修改数组元素
func changeEle(arr *[3]int) {
arr[0] = 1000
fmt.Println(arr[0])
}
func main() {
var arr1 [5]int
arr1[0] = 10
fmt.Println(arr1[0])
arr2 := [3]int{1, 2, 3}
fmt.Println(arr2)
arr3 := [...]int{1, 3, 4, 5, 6, 8}
fmt.Println(arr3)
//循环数组的值
for i := 0; i < len(arr3); i++ {
fmt.Println(arr3[i])
}
//循环输出数组的下标和值
for i, num := range arr3 {
fmt.Println("数组下标:", i, "对应下标的值:", num)
}
//只循环数组的值
for _, num := range arr3 {
fmt.Println("对应下标的值:", num)
}
arr4 := [2][4]int{
{1, 2, 3, 4},
{5, 6, 7, 8},
}
fmt.Println(arr4)
arr5 := [3]int{1, 2, 3}
changeEle(&arr5)
fmt.Println(arr5)
}
- 数组声明需要指定元素类型和元素个数,var var_name [SIZE] var_type
- 初始话数组中 { }中的元素个数不能大于【】中的数
- 可以使用…来忽略数组大小,会根据元素的个数来设置数组的大小
- 多维数组本质也是一维数组
切片概念
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5}
s1 := arr[2:5]
fmt.Println(s1)
s2 := make([]int, 5)
fmt.Println(s2)
}
切片的长度“len”是第一个元素到切片的最后一个源,容量“cap” 是切片的第一个元素到最后一个
- 初始话切片,【】表示切片类型,不需要指定大小
- 也可以通过make关键字进行初始话,s1 := make ([]T, length, capacity)
- 指定数组的索引初始话切片,是数组的引用
- 切片之上还可以继续指定切片
切片的操作
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := arr[2:6]
fmt.Println(s1, len(s1), cap(s1), arr)
s1 = append(s1, 10)
fmt.Println(s1, len(s1), cap(s1), arr)
fmt.Println("====================")
//遍历切片
var s2 []int
for i := 0; i < 10; i++ {
s2 = append(s2, i)
}
fmt.Println(s2)
//利用append删除元素
s3 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(s3)
s3 = append(s3[:4], s3[5:]...)
fmt.Println(s3)
//使用make进行声明切片
s4 := make([]int, 10)
fmt.Println(s4)
}
如果原有的切片容量小于1024,那么扩容就是2倍的容量进行扩容
- 添加元素时,如果超过cap会重新生成一个新的底层数组
- 需要一个变量接受append后的值
- 切片在未初始化之前默认为nil
- 可以使用append来达到删除元素的功能
切片扩容机制
- 当原有的切片容量小于1024时,那么扩容就是2倍的容量进行扩容
- 当原有的切片容量大于等于1024时,那么扩容就是在原有的基础上增加1/4
map集合
var m1 map[string]int //m == nil
m1 = make(map[string]int) //初始化map
m1["a"] = 10
//直接初始化map
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
//判断key值是否存在,如果存在ok等于true,否则为false
if val, ok := m1["e"]; ok {
fmt.Println(val)
} else {
}
//使用range循环map
for k,v := range m2 {
fmt.Printf("key=%s,val=%d\n", k, v)
}
delete(m2, "a")
- 直接通过var来声明,不初始化就是零值:nil,不能存放k/v
- 可以通过make来初始化map,初始化之后是空map,可以存放k/v
- 判断值是否存在:val ok := map[“key”]
- 可以直接使用delete来删除map中的key
- 可以使用range关键字遍历map
- map是无序的哈希表
- 除了slice,map,funcation之外的内建类型都可以作为key
struct结构体
struct结构体,类似于java的对象
type Book struct {
id int
title string
author string
subject string
}
工厂方法,将结构体变成小写(私有的)来强制使用工厂函数实例化
func NewBook(id int, title, author, subject string) *Book {
return &Book{
id,
title,
author,
subject,
}
}
实例化结构体的方法
//使用new关键字实例化struct
var book1 *Book
book1 = new(Book)
book1.id = 1001
book1.title = "go in action"
book1.author = "james"
book1.subject = "about golang"
//实例化struct
book2 := Book{
id: 1002,
title: "python in action",
author: "jordan",
subject: "about python",
}
//使用工厂函数实例化struct
book3 := NewBook(1003, "java in action", "gsl", "java in action")
定义结构体的方法
//定义struct结构体方法
func (book *Book) String() string {
return fmt.Sprintf("id=%d, title=%s, author=%s, subject=%s\n", book.id, book.title, book.author, book.subject)
}
//定义struct结构体方法获取author作者
func (book *Book) GetAuthor() string {
return book.author
}
- go语言没有继承和多态,但是有接口的概念
- 使用new函数给一个新的结构体分配内存,它的返回值指向已分配内存的指针
- 给结构体定义的函数叫方法,前面需要带上结构体指针声明
内嵌结构体
type book struct {
Id int "this is a book id"
Title string "this is a book title"
Author string "this is a book author"
Subject string "this is a book subject"
}
type techBook struct {
Cat string
title string
int //匿名字段
book //匿名字段,内嵌结构体
}
func InitTechBook() {
bk := NewBook(1, "title", "author", "subject")
tb := new(techBook)
tb.Cat = "tech"
tb.int = 10
tb.book = *bk
fmt.Println("TechBook cat=", tb.Cat)
fmt.Println("TechBook int=", tb.int)
fmt.Println("TechBook book=", tb.book.String())
fmt.Println(tb.Title)
}
- 结构体中的字段除了有名字和类型外,还可以有一个可选的标签(tag)
- 结构体可以包含一个或多个匿名或内嵌字段
- 匿名类型的可见方法也同行被内嵌,在效果上等同于继承