DAY 100 go04

1 数组
2 切片
3 maps


package main

import "fmt"

// 回顾

func main() {
//1 连续存储,相同类型
//var a [3]int=[3]int{1,2,3}
//var a [3]int=[3]int{1,2}
//var a [3]int=[3]int{2:999}
//var a =[3]int{2:999}
//var a =[...]int{2:999}
//a :=[3]int{2:999}
//fmt.Println(a[0])
//循环(两种方式:索引,迭代)
// 多维数组
// 长度
//fmt.Println(len(a))
// 数组是值类型:当参数传递,在函数中修改,不会影响原来的(copy),值类型如果不初始化,有默认值

//2 切片:由于数组用起来不是特别方便,长度固定
// 本身不存储数据{指针,长度,容量},是对底层数组的引用  a[3]
// 定义并初始化
//var a []int=[]int{1,3,4}
//var s=[10]int{1,2,3,4,}
//var a []int=s[5:8]
//var a []int =make([]int,3,4)
// 长度和容量:长度是目前切片中存储值的数量(len),容量是可以使用的底层数组的大小(cap)
// 切片的取值赋值 按索引,不能越界(长度)
// 追加切片(
//如果不超过底层数组长度,就是改变底层数组,长度变化,容量不变
//如果超过底层数组长度,新创建一个数组,让切片指向新的数组,长度变化,容量变化(原来切片容量的两倍)
//a=append(a,1,2,3,)
// 切片的函数传递(引用类型),引用类型的空值是nil,值类型的空值是类型的0值,当参数传递,修改会影响原来的
// // 在函数中append坑
// copy函数使用
// 多维切片(第二维,也需要初始化)


//maps:字典,hash
var a map[string]string= map[string]string{"name":"lqz","age":"18","hobby":"篮球","height":"180"}
//var a map[string]string=make(map[string]string)
// 赋值
//a["name"]="egon"
//fmt.Println(a)
//取值
//fmt.Println(a["name"])
//v,ok:=a["xx"]  //如果存在,v就是值,ok就是true  如果不存在,v就是Value值的空值,ok是false
//fmt.Println(v)
//fmt.Println(ok)
//增加值
a["xxx"]="xxx"
fmt.Println(a)

//删除元素 delete  通过key删除
delete(a,"ssss")

// 长度
//fmt.Println(len(a))
// 引用类型:空值是nil,当参数传递,会修改原来的
test(a)
fmt.Println(a)


// map存储是无序的
for key,value:=range a{
//fmt.Println("key值是:",key,"value值是:",value)
fmt.Printf("key值是:%v,value值是%v\n",key,value)
//fmt.Println()
}

//go语言中实现一个有序map

// 所有的hash类型的底层存储是如何实现的(底层基于数组或链表)
//hash冲突解决:
//1 开放地址方法:线性探测 ,再平方探测
//2 链式地址法
//3 再哈希法




}

func test(a map[string]string) {
a["name"]="张三"
a["x"]="x"
a["xx"]="xx"
a["xxx"]="xxxx"
a["xxxx"]="xxxxx"

fmt.Println(a)


}

 

1 字符串

package main

import (
"fmt"
"unicode/utf8"
)

// 字符串
//Go中的字符串是兼容 Unicode 编码的,并且使用 UTF-8 进行编码。

func main() {
// 0 go 语言是强类型
//var a int=199
//var b float32=99.99
//fmt.Println(a+int(b))

// 1 定义字符串
//var b byte   uint8 一个字节
//var c rune   int32 4个字节---》表示出所有的utf-8
s:="中国"
//不能修改,只能取

//fmt.Println(s[0])
//fmt.Printf("%T",s[0])
//fmt.Println(string(s[0]))
//fmt.Println(s)

// 2 循环字符串(索引,迭代)
//for i:=0;i<len(s);i++{ // 拿一个个字节
// fmt.Println(string(s[i]))
//}
//
//for _,v:=range s{ // 按字符循环
// fmt.Println(string(v))
//}

// 3 字符串长度
// 字节长度
fmt.Println(len(s))
// 字符长度
fmt.Println(utf8.RuneCountInString(s))
}

 

2 指针

package main

import "fmt"

// 指针:指针是一种存储变量内存地址(Memory Address)的变量
//1 & 取地址符号,加在变量前,表示取该变量的地址
//2 * 如果放在类型前,表示指向该类型的指针
//3 * 放在变量前,表示解引用(反解),通过地址取出地址对应的值
func main() {

//var a int =10
//fmt.Println(a)
//1 定义一个指针,指向变量a (存储变量a的地址)
//var p = &a
//fmt.Println(p)
//var p1 = &p
//fmt.Println(p1)

// 2 指针类型的变量
//p :=&a
//p是指向int类型 的指针
//var p *int=&a
//var p1 **int = &p
//var p2 ***int=&p1
//fmt.Println(p)
//fmt.Println(p1)
//fmt.Println(p2)
//fmt.Println(*p2)
//fmt.Println(*p1)
//fmt.Println(*p)
//
//fmt.Println(***p2)

//3 定义一个指向其他类型的指针
//s:="hello world"
//var a *string=&s
//fmt.Println(a)
//fmt.Println(*a)

//a:=[3]int{1,2,3}
//var b *[3]int=&a
//fmt.Println(b)
//fmt.Println(*b)

//var a []int=[]int{1,2,3}
//var b *[]int=&a
//fmt.Println(*b)

// 4 零值(引用)
//var a *int
//fmt.Println(a) //nil,
//fmt.Println(*a)
//fmt.Println(&a)

//5 向函数传递指针参数
//i:=10
//var a *int=&i
//fmt.Println("调用函数之前:",a)
//test1(a)
//fmt.Println("函数外的a:",*a)

//6 不要向函数传递数组的指针,而应该使用切片
//var a [4]int=[4]int{2,3,4}
//var b *[3]int=&a
// 传到函数中修改原来的值
//test3(b)
//fmt.Println("外部的:",a)
//
//test4(a[:])
//fmt.Println("外部的:",a)

// 7 指针不能运算(go黑魔法,允许的)
//var a [4]int=[4]int{2,3,4}
//var b *[4]int=&a
//b++

// 8 可变长参数
//test5(1,2,3,4,4,5,6,7,8,98)
var a []int=[]int{1,2,3}
test5(a...)  // 如果想传切片,需要a... 相当于打散了传过去

}

func test5(a ...int) {
fmt.Println(a)
fmt.Printf("%T",a)

}
func test4(a []int) {
a[0] = 99
fmt.Println(a)

}
func test3(a *[3]int) {
fmt.Println(a)
//(*a)[0]=99
a[0] = 99 //等同于上面,先解引用,再改值,内部自动解引用
fmt.Println(a)
}

func test1(a *int) {
fmt.Println("函数内部:", *a)
*a++
fmt.Println(*a)
}



// 数组指针和指针数组

 

3 结构体

package main

// go 不是一个纯粹的面向对象,没有类的概念,但是可以通过结构体+方法实现面向对象的功能
// 结构体:结构体是用户定义的类型,表示若干个字段(Field)的集合。一系列属性的集合

//1  定义一个结构体
//type 结构体名 struct{
// 字段
// 字段
//}
//type Person struct {
// name string
// age  uint8
// sex  string
//}

//// 8 匿名字段
//type Person struct {
// string   // 字段没有名字,属性类型就是字段名,所以不能重复
// uint8
// sex string
//
//}

// 9 结构体嵌套(类似于面向对象的继承,Person继承Hobby)
type Hobby struct {
id int
HobbyName string
}
type Person struct {
name string
age uint8
sex string
//hobby Hobby  // 结构体嵌套
//Hobby  // 匿名字段
}

type Person1 struct {
hobbys []string
}

//type Person struct {
// name string
// age uint8
// sex string
// hobby struct{  //嵌套匿名结构体
// id int
// name string
// }
//}

func main() {
// 2 使用结构体
//var p Person  // 定义,没有初始化,值类型,空值是 属性的0值
//var p Person = Person{"lqz", 18, "男"}
//fmt.Println(p)

// 3 匿名结构体 (type关键字和名字都省略),
//有什么用?后期操作多个变量,可以把多个变量放到一个匿名结构体中,这样使用结构体对象可以直接拿到所有变量
//a:= struct {
// name string
// age  int
//}{"lqz", 19}
//fmt.Println(a.name)
//fmt.Println(a.age)
//a.age=20
//fmt.Println(a)

// 4 结构体零值(值类型,零值是属性的零值)
//var p Person
//fmt.Println(p) // 有默认值
//var p Person=Person{"lqz",19,"男"}  // 按位置初始化,有几个值就要传几个值
//var p Person=Person{name:"lqz",age:19} // 按关键字初始化,顺序无所谓,可以传部分
//fmt.Println(p)

// 5 访问结构体字段 ( 通过. 访问)
//var p Person=Person{name:"lqz",age:19} // 按关键字初始化,顺序无所谓,可以传部分
//fmt.Println(p.name)

//6 结构体指针
//var p Person=Person{name:"lqz",age:19} // 按关键字初始化,顺序无所谓,可以传部分
//var p1 *Person=&p
//fmt.Println(p1)

// 结构体指针初始化
//var p2 *Person=&Person{name:"lqz",age:19}
//fmt.Println(p2)
//fmt.Println((*p2).name)
//fmt.Println(p2.name)  // go语言帮你解引用了

// 7 匿名字段(字段没有名字)    ---》用作变量提升---》面向对象的继承
//p:=Person{"lqz",19,"男"}
//p:=Person{string:"lqz",uint8:19,sex:"男"}
//fmt.Println(p.sex)
//fmt.Println(p.string)


// 8 结构体嵌套
//p:=Person{"lqz",19,"男",Hobby{id:1,name:"篮球"}}
//p:=Person{name:"lqz",age:19,sex:"男",hobby:Hobby{id:1,name:"篮球"}}
//fmt.Println(p.name)
//fmt.Println(p.hobby)
//fmt.Println(p.hobby.id)
//fmt.Println(p.hobby.name)

// 9 提升字段(类似于面向对象继承)
//p:=Person{"lqz",19,"男",Hobby{1,"足球"}}
//p:=Person{name:"lqz",age:19,sex:"男",Hobby:Hobby{1,"足球"}}
//fmt.Println(p.name)
//fmt.Println(p.Hobby)
//fmt.Println(p.Hobby.id)
//fmt.Println(p.id)  //正常应该p.Hobby.id,但是限制变量提升了,提升到上一层了
//fmt.Println(p.name)
//fmt.Println(p.HobbyName)
// 如果Person和Hobby中有同名字段,就是用Person,如果想用Hobby,需要指名道姓的使用

// 10 导出结构体和字段   ---》大写字母开头

//var p entity.BlackPerson=entity.BlackPerson{"张三",19}
//var p entity.BlackPerson
//fmt.Println(p)
//p.Name="李四"
//fmt.Println(p)

//var p entity.BlackPerson=entity.NewBlackPerson("李四",88)
//fmt.Println(p.Name)
//fmt.Println(p.age)  //非导出字段,不能使用

// 11 结构体相等性
//p:=Person{"lqz",19,"男"}
//p1:=Person{"lqz1",19,"男"}
//if p==p1{
//fmt.Println("等于")
//}

//p1:=Person1{hobbys: []string{"篮球","足球"}}
//p2:=Person1{hobbys: []string{"篮球","足球"}}
//if p1==p2{
//}







}

 

4 方法

package main

import "fmt"

// 接口:一系列方法的集合

// 定义一个接口
// 定义了一个鸭子接口,内部有run和speak方法
type Duck interface {
run()
speak()
}

// 定义一个结构体
type TDuck struct {
name string
age int
wife string
}

// 结构体实现结构---》只要实现接口中的所有方法,就叫实现了该接口----》鸭子类型

//方法 TDuck 实现了run方法
func (t TDuck)run() {
fmt.Println("run")
}
func (t TDuck)speak() {
fmt.Println("speak")
}

func main() {

t:=TDuck{"张三",19,"迪丽热巴"}
fmt.Println(t.wife)
t.run()
}

 

扩展

# Python字典有序,且更高效
https://www.cnblogs.com/xiaoyuanqujing/articles/12008689.html
posted @ 2021-06-17 16:49  DEJAVU_ERIC  阅读(98)  评论(0编辑  收藏  举报