切片类型、map、字符串、指针、结构体、方法、
一、切片类型
切片类型:是由数组建立的一种方便灵活的且功能强大的包装,切片本身不拥有任何数据类型,他只是对现有数组的引用。
即:指向了一个地址,本身不拥有数据。

package main import "fmt" func main() { //切片定义的第一种方式,由数组切出来 //var a [8]int=[8]int{1,2,3,4,5,6,7,8} ////只是对数组的引用 //var b []int=a[2:6] //fmt.Println(b) //a[2]=30 //fmt.Println(b) //b[1]=40 //fmt.Println(b) //fmt.Println(a) ////原数组的修改会影响切片 ////切片的修改也会影响底层数组 //a[1]=20 //fmt.Println(b) //更多用法,没有步长 //var a [8]int=[8]int{1,2,3,4,5,6,7,8} //b:=a[:4] //fmt.Println(b) //第二种方式,直接定义 //切片空值是?nil类型 //var a []int //if a==nil{ // fmt.Println("我是空的") //} //a[0]=10 //fmt.Println(a) //定义并初始化,第一个参数是类型,第二个参数是切片的长度,第三个参数是底层数组长度,也就是切片的容量 //var a []int=make([]int,3) //fmt.Println(a) //切片的长度和容量(len cap:容量) //切片的长度就是它所包含的元素个数。 //切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。 //var a [8]int=[8]int{1,2,3,4,5,6,7,8} //var b []int=a[2:6] //fmt.Println(len(b)) //fmt.Println(cap(b)) //var a []int=make([]int,3,4) //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //切片追加值(即给切片赋值) //var a [8]int=[8]int{1,2,3,4,5,6,7,8} //var b []int=a[2:6] //fmt.Println(len(b)) //4 //fmt.Println(cap(b)) //6 ////内置函数append,append函数的返回值也为切片 //b=append(b,555) //b=append(b,666) //追加两个值之后,容量为6,长度为6 //底层数组a的相应位置数据也被修改了 //fmt.Println(b) //fmt.Println(len(b)) //fmt.Println(cap(b)) //b[0]=999 //fmt.Println(a) //a[2]变为999 //容量满了再继续追加 //b=append(b,777) //fmt.Println(b) //长度为7 //fmt.Println(len(b)) //切片容量翻倍为12 //fmt.Println(cap(b)) //当切片超出底层数组长度时,再进行追加会重新创建一个数组,修改切片中的值不会影响原数组中的值 //b[0]=999 //fmt.Println(b) //fmt.Println(a) //var b =make([]int,3,4) //fmt.Println(b) //[0,0,0] //b=append(b,4) //fmt.Println(b) //[0,0,0,4] //fmt.Println(len(b)) //4 //fmt.Println(cap(b)) //4 //b=append(b,5) //fmt.Println(len(b)) //5 //fmt.Println(cap(b)) //8 //切片的修改 //var b =make([]int,3,4) //b[0]=999 //fmt.Println(b) //var b =make([]int,4,4) //fmt.Println(len(b)) //fmt.Println(cap(b)) //切片的函数传递 //var b =make([]int,3,4) //test(b) //在函数中修改之后原b切片的值也会改变,即切片是引用传递 //fmt.Println(b) //切片的数据结构表示 //type slice struct { // Length int // Capacity int // ZerothElement *byte //} //多维切片 //var a [][]string=make([][]string,2,3) //fmt.Println(a[0]) //[]为空切片,只初始化了外层切片 //a[0]=make([]string,2,3) //为内层切片初始化 //if a[0]==nil{ // fmt.Println("xxxx") //} //切片初始化的方法 //var a []int=[]int{1,2,3} //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //多维切片初始化 //var a [][]string=[][]string{{"1","2"},{"3","4"}} //fmt.Println(a) //fmt.Println(len(a)) //fmt.Println(cap(a)) //a[0][1]="999" //fmt.Println(a) //a[1][0]="999" //var a []int=[]int{1,2} //fmt.Println(a) //a=append(a,3) //fmt.Println(len(a)) //fmt.Println(cap(a)) //a[2]=99 //a[3]=888 //fmt.Println(a) //copy函数 var a =make([]int,3,10000) //底层数组很大,耗费内存 a[1]=99 a[2]=888 fmt.Println(a) //var b =make([]int,4,4) var b =make([]int,2,4) fmt.Println(b) //将a copy 到另一个切片上去 copy(b,a) fmt.Println(b) } func test(b []int) { b[0]=999 fmt.Println(b) }
可变长参数:

package main //可变长参数 import "fmt" //可变长参数 func main() { //var a =[]int{1,2,4,} //test1(1,2,3,4) //相当于打散了 //test1(a...) //veggies := []string{"potatoes", "tomatoes", "brinjal"} //fruits := []string{"oranges", "apples"} //food := append(veggies, fruits...) //fmt.Println("food:",food) //循环多维切片 pls := [][]string { {"C", "C++"}, {"JavaScript"}, {"Go", "Rust"}, } fmt.Println(pls) for _,v:=range pls { for _,v1:=range v{ fmt.Println(v1) } } } func test1(a ...int) { fmt.Println(a) fmt.Printf("%T",a) }
二、map
map:在Go中将键(key)值(value)关联起来的内置类型,通过相应的键来获取相应的值。
map中放函数和用map实现set练习:

package main //回顾 //func main() { //指针数组和数组指针 //数组里面放指针 指向数组的指针 // //a:=10 //b:=20 ////数组里面放指针 //c:=[2]*int{&a,&b} //fmt.Println(c) //指向数组的指针 //a:=[2]int{1,2} //var b *[2]int //b=&a //fmt.Println(b) //} //-map内放函数 //func main() { // var m map[int]func(a int)int=make(map[int]func(a int)int) // m[1]= func(a int) int { // // return a // } // m[2]= func(a int) int { // return a*a // } // m[3]= func(a int) int { // return a*a*a // } // // fmt.Println(m[1](9)) // fmt.Println(m[2](9)) // fmt.Println(m[3](9)) //} //-通过map实现set func main() { //集合 //可以放值,如果重复了,放不进去 //可以获取长度 //判断一个值是否在集合内 //把集合内所有元素打印出来 // //var m map[string]bool=make(map[string]bool) //m["lqz"]=true //m["egon"]=true // //m["lqz"]=true // //fmt.Println(len(m)) ////"aa"是否在集合内 //if m["aa"]{ // fmt.Println("在里面") //}else { // fmt.Println("不再") //} //for k,_:=range m{ // fmt.Println(k) //} }

//maps package main import "fmt" func main() { //maps的定义 //map的key值必须可hash //var a map[键值类型]value值类型 //map的空值是nil类型 //也是引用类型,在函数中修改原来的值也会被修改 //var a map[int]string //fmt.Println(a) //if a==nil{ // fmt.Println("xxxx") //} //map的赋值跟取值 //map的初始化 //var a map[int]string=make(map[int]string) //fmt.Println(a) ////if a==nil{ //// fmt.Println("xxxxx") ////} //a[1]="100" //a[2]="888" //fmt.Println(a) //fmt.Println(a[1]) ////取一个不存在的key值会?返回value值的空值的默认值(int为0,string为“”) ////fmt.Println(a[9]) //var b map[int]int=make(map[int]int) //b[1]=100 //fmt.Println(b) ////fmt.Println(b[9]) //if v,ok:=a[9];ok{ // fmt.Println("=-====",v) //}else { // fmt.Println("该值不存在") //} //v,ok:=a[1] //fmt.Println(v) //fmt.Println(ok) //定义和初始化的第二种方式 //var a =map[int]string{1:"10",2:"100"} ////a[1] //fmt.Println(a[1]) //字典删除元素,内置函数 //var a =map[int]string{1:"10",2:"100"} ////delete(a,2) //delete(a,3) //fmt.Println(a) //map长度 //var a =map[int]string{1:"10",2:"100"} //delete(a,1) //a[10]="999" //fmt.Println(len(a)) //Map 是引用类型 //var a =map[int]string{1:"10",2:"100"} //test4(a) //fmt.Println(a) //Map 的相等性 //map1 := map[string]int{ // "one": 1, // "two": 2, //} // //map2 := map1 //if map1 == map2 { //报错 //} //map循环出所有元素 ////map是无序的 //for k,v:=range a{ // fmt.Println(k) // fmt.Println(v) //} //补充:切片删除元素 //var a =[]int{1,2,3,4,5,6} //a=append(a[0:2],a[3:]...) //fmt.Println(a) } func test4(a map[int]string) { a[1]="888" fmt.Println(a) } //把map做成有序作业
三、字符串
字符串:

package main import ( "fmt" "unicode/utf8" ) func main() { //name := "Hello World刘清政" //name:="刘" //字符串长度,len统计字节数 //在go中string类型都是utf-8编码 //fmt.Println(len(name)) //fmt.Println(utf8.RuneCountInString(name)) //unicode是一个字符编码对照表 //循环 //字符串是个只读切片 //name := "name刘" //循环的是字节 //for i:=0;i<len(name);i++{ // fmt.Println(string(name[i])) // fmt.Printf("%T",name[i]) // fmt.Println() //} //循环的是字符 //for _,v:=range name{ // fmt.Println(string(v)) // fmt.Printf("%T",v) // fmt.Println() //} //name := "name刘" //name[0]=99 //fmt.Println(name[0]) //fmt.Println(string(name[0])) byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9} str := string(byteSlice) a:=len(str) b:=utf8.RuneCountInString(str) fmt.Println(b) fmt.Println(a) fmt.Println(str) }
四、指针
指针:是一种存储变量内存地址的变量。

//指针 package main import "fmt" func main() { //&取地址符号 //* 放在类型旁边,表示指向这个类型的指针 //* 放在变量旁边,表示解引用(反解) //a:=10 //b就是一个指针 指向int类型的指针 //b:=&a //d:="sss" //var c *string=&d //var b *int =&a //fmt.Println(b) //fmt.Println(*b) //c:=&b //var c **int=&b //fmt.Println(*(*c)) //指针的零值(Zero Value),nil类型 //var a *int //fmt.Println(a) //向函数传递指针参数 //a:=10 ////b:=&a ////test6(b) ////fmt.Println(a) //test7(a) //fmt.Println(a) //func test6(b *int) { // //*b 就是 a a++ // *b++ //原来a的值也会被修改 // fmt.Println(*b) //} //func test7(b int) { // b++ //原来a的值不会改变 // fmt.Println(b) //不要向函数传递数组的指针,而应该使用切片 //var a [100]int ////test9(&a) ////fmt.Println(a) //test10(a[:]) //fmt.Println(a) //Go 不支持指针运算 } // 若向函数传递指针则数组指针的长度写死了,受众范围小 func test9(a *[4]int) { (*a)[0]=999 //底层数组也会受到影响 fmt.Println(a) } func test10(a []int) { //使用切片同样可以修改底层数组 a[0]=999 fmt.Println(a) } //}
五、结构体

package main //结构体:是一系列属性的集合 //定义一个人结构体 //type关键字 结构体名字 struct{} //type Person struct { // name string // sex ,age int // //} //匿名字段表示字段没有名字 //type Person struct { // string // int //} //嵌套结构体 //type Person struct { // name string // sex ,age int // hobby Hobby // //} //type Hobby struct { // id int // name string //} //结构体嵌套+匿名字段 type Person struct { name string sex ,age int Hobby } type Hobby struct { id int //hobbyname string name string } func main() { //person :=Person{} //定义没有初始化 //结构体是值类型 //var person Person //var person Person=Person{name:"lqz"} //var person Person=Person{"lqz",1,19} ////person.name="lqz" //fmt.Println(person.name) //匿名结构体 //age:=10 //name:="lqz" // //a:=struct { // name string // age int //}{"lqz",19} //fmt.Printf(a.name) //结构体的零值 //结构体指针 //p:=Person{name:"lqz"} ////pPoint:=&p //var pPoint *Person=&p ////fmt.Println(pPoint) ////fmt.Println((*pPoint).name) //可以直接指针.变量名来获取 //fmt.Println(pPoint.name) //匿名字段(用作变量提升) //p:=Person{"lqz",19} //用类型名来代替变量名 //p:=Person{string:"lqz",int:19} //fmt.Println(p.string) //嵌套结构体 //p:=Person{name:"lqz",hobby:Hobby{10,"篮球"}} //p:=Person{name:"lqz",hobby:Hobby{id:10,name:"篮球"}} //p.hobby.id=101 // //fmt.Println(p.hobby.name) //结构体嵌套加匿名字段 //p:=Person{name:"lqz",Hobby:Hobby{10,"篮球"}} ////取p中的hobbyname //fmt.Println(p.Hobby.hobbyname) //fmt.Println(p.hobbyname) //变量提升过程中如果有重名的,就不提升了 //p:=Person{name:"lqz",Hobby:Hobby{10,"篮球"}} //fmt.Println(p.Hobby.name) //fmt.Println(p.name) //结构体相等性 }
六、方法
方法:方法其实就是一个函数,在func关键字和方法名之间加入了一个特殊的接收器类型,接收器可以是结构体类型,或者非结构体类型,接收器是可以在方法的内部访问的

package main import "fmt" //方法 其实就是一个函数 type Person struct { name string age int sex int } //语法 //func (a Person) getName() { // //} //方法给对象用 //给Person结构体加一个打印名字的方法 func (a Person)printName() { fmt.Println(a.name) } //func (a Person)changeName(name string) { // a.name=name // fmt.Println(a) //} func (a *Person)changeName(name string) { a.name=name fmt.Println(a) } //func printName(a Person) { // fmt.Println(a.name) //} //func printName(a *Person) { // fmt.Println(a.name) //} func main() { //var p *Person=&Person{name:"lqz"} //这种也可以,go给你处理了 //var p Person=Person{name:"lqz"} //p.changeName("egon") 值类型的接收器,不会影响原p的值 //fmt.Println(p) //p.printName() //为什么我们已经有函数了还需要方法呢 //执行函数 //printName(p) //printName(&p) //指针接收器与值接收器 //func (值)changeName(name string):在内部修改值,不会影响外部的值 //func (指针)changeName(name string):在内部修改值,会影响外部的值 //那么什么时候使用指针接收器,什么时候使用值接收器 //想修改原值,就用指针接收器 //匿名字段的方法 }
非结构体上的方法:

package main import "fmt" //在非结构体上的方法 //重命名 type MyInt int func (i *MyInt)add() { (*i)++ fmt.Println(*i) } func main() { var a MyInt=10 a.add() fmt.Println(a) }
在方法中使用值接收器 与 在函数中使用值参数
在方法中使用指针接收器 与 在函数中使用指针参数

package main import "fmt" //在方法中使用值接收器 与 在函数中使用值参数 //在方法中使用指针接收器 与 在函数中使用指针参数 type Person2 struct { name string age int sex int } //方法中使用值接收器 func (a Person2)printName() { fmt.Println(a.name) } //方法中使用指针接收器 func (a *Person2)printName2() { fmt.Println(a.name) } //函数中使用值参数 func printName(a Person2) { fmt.Println(a.name) } //在函数中使用指针参数 func printName2(a *Person2) { fmt.Println(a.name) } func main() { //p:=&Person2{name:"lqz"} //调用值接收器 //p.printName() //调用指针接收器 //p.printName2() //调用值函数 //printName(p) //调用指针函数 //printName2(&p) //方法中: //不管是指针接收器还是值接收器,都可以使用值来调用 //不管是指针接收器还是值接收器,都可以使用指针来调用 //函数中: //是什么参数,就得传什么参数 }
七、接口
接口:在面向对象中,接口一般定义一个对象的行为,接口只是制定了对象应该做什么,至于如何实现这个行为,则由对象本身去决定。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)