go语言基础变量与拷贝

记录一下自己的学习过程,顺带水一篇文章

go语言基础变量类型

变量定义

var a int/float32/float64/string/bool/... = value
var b := value //自动确定类型
var c [3][4] int //2维int型数组
interface{}//存储任意类型
//可以只声明不赋值,数值类型默认为0 布尔类型默认为false 字符串为"" 其他基本为nil

nil

nil 是一个预先声明的标识符,指针、通道、函数、接口、map、切片的零值就是nil

nil 是没有默认类型的,他的类型具有不确定性,我们在使用它时必须要提供足够的信息能够让编译器推断 nil 期望的类型

以下是 nil 的一些注意事项:
1. 声明一个 nil 的 map,map 可以读数据,但是不能写数据
2. 关闭一个 nil 的 channel 会引发 panic
3. nil切片不能进行索引访问,会引发 panic
4. 方法接收者为 nil 时,如果在方法内使用到了会引发 panic
5. 空指针一个没有任何值的指针

切片(变长数组)

切片的声明

var s1 []int  //会被初始化维nil
s2 := []int{}  //不为nil,为空
var s3 []int = make([]int, 0, 0) //参数分别为,make类型,初始长度,缓存大小  不为nil,为空

arr := [5]int{1, 2, 3, 4, 5} //数组
var s6 []int  //切片
s6 = arr[1:4]  //从数组切片  切片是数组的一个引用
s7 = arr[:3:8] //s7切片arr的0-2,并切cap设置为8(最多存放8个数据 0-7)

s8 [][]int{  //[]int类型的切片 2维变长数组
		[]int{1, 2, 3},  //初始化值
		[]int{100, 200},
		[]int{11, 22, 33, 44},
	}

切片的读写

data := [...]int{0, 1, 2, 3, 4, 5}
s := data[2:4]
s[0] += 100

结果是 data 的数据改变了。切片的一切修改都是在底层数组上的修改( make 创建的切片会自动分配一个数组)

切片的函数 append/copy

var a = []int{1, 2, 3}
b := append(a,4) //b:{1,2,3,4} append 添加元素
c := make([]int,3)
copy(c,a) //将a的内容拷贝到c  这是深拷贝,c的修改不会影响a
d := a //用a给d赋值,这是浅拷贝,d的修改会影响a

切片/数组遍历 range

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := data[:]
for index, value := range slice {
	fmt.Printf(index, value)
}

map

map 声明

map[KeyType]ValueType//{可以添加数据}  //不添加会被初始化为nil
make(map[KeyType]ValueType, 0) //初始大小为0的map 不为nil

map的增删改查

a := make(map[string]int, 8)
a["DLUT"] = 985 //添加 DLUT 985
a["DLUT-开发区"] = 985
a["DLUT-开发区"] = 211 //修改键值对
delete(a,"DLUT-开发区") //删除 DLUT-开发区 211
v,ok = a["DLUT"]  //查找DLUT对应的值,如果有则ok为true,v为对应的值  否则ok为false,v为对应类型的0值

map的遍历

scoreMap := make(map[string]int)
scoreMap["张三"] = 90
scoreMap["小明"] = 100
scoreMap["娜扎"] = 60
for k, v := range scoreMap {
    fmt.Println(k, v) //顺序不确定
}

//以下是根据key值大小排序的遍历
var keys = make([]string, 0, 200)
for key := range scoreMap {
    keys = append(keys, key)
}
for _, key := range keys {
		fmt.Println(key, scoreMap[key])
}

map的拷贝

mapp := map[string]int{
    "steve": 12000,
    "jamie": 15000,
} //map是引用,所以作为函数参数时,map的修改可以被传到函数外
newmapp := mapp //浅拷贝
newmapp["steve"] = 18000 //mapp也会被修改

结构体

结构体的声明

type MyStruct struct { //关键词为type 和 struct
	Name string
	Age  int
}

func (test MyStruct) test() (){
    //等效结构体函数、类成员函数
}
func (test *MyStruct) test() (){
    //等效结构体函数、类成员函数
    //使用指针传入可以对结构体的数据进行修改
}

结构体的实例化与初始化

type test struct { //关键词为type 和 struct
	Name string
	Age  int
}

t1 := test{"Alice", 30}
t2 := test{Name: "Alice"} // Age字段会被自动初始化为0

t3 := new(test) //new返回一个对应类型的指针,所有字段都被初始化为零值
(*t3).Name="123"

var t4 test
t4.Name = "123"

var t5 = &test{}//等效与new

结构体匿名字段

结构体允许其成员字段在申明的时候没有字段名只有字段类型,这种没有名字的字段就称为匿名字段

匿名字段并不是说没有字段名,而是默认会采用类型名作为字段名

结构体要求字段名唯一,因此一个结构体中同种类型的匿名字段只能有一个

type Person struct {
	string
	int
}
person := Person{
	"GGBond",
	18,
}

//可以通过匿名字段实现结构体继承
type Animal struct {
	name string
}
type Dog struct {
	Feet    int8
	*Animal 
}

结构体的JSON序列化与tag

type userInfo struct {
	Name  string  //首字母大写才能使用marshal进行js序列化
	Age   int `json:"age"`  //使用tag实现json序列化该字段时的key
	Hobby []string
}
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)  //marshal生成一个byte数组 可以等效成字符串

var b userInfo
err = json.Unmarshal(buf, &b)  //反序列化

结构体的拷贝问题

type Person struct {
	name   string
	age    int8
	dreams []string  //由于切片是引用类型,如果涉及到这个元素的赋值,往往需要写一个新的方法来实现深拷贝
}
func (p *Person) SetDreams(dreams []string) {
	p.dreams = make([]string, len(dreams))
	copy(p.dreams, dreams)
}

拷贝

值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。

引用类型的数据,默认全部都是浅复制,Slice,Map。

深拷贝

对于值类型的数据可以直接使用=进行深拷贝

切片

使用 copy() 函数进行深拷贝

matA := [][]int{
        {0, 1, 1, 0},
        {0, 1, 1, 1},
        {1, 1, 1, 0},
    }
matB := make([][]int, len(matA))
for i := range matA {
    matB[i] = make([]int, len(matA[i])) // 注意初始化长度
    copy(matB[i], matA[i])
}

map

手写函数实现深拷贝

newMap := make(map[string]int)
for k, v := range Map {
    newMap[k] = v
}

浅拷贝

不赘述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值