golang基础篇

一、切片:

1、主要看指针指向位置
比如 一个切片 var s []int{1,2,3,4,5,6,7}
指针指向0位
长度是 7 ,容量是7
a := s[2:4]
指针指向index为2为
a 长度是 2 (元素是2,3) 容量是5 (从index为2往右算或者max_len 减去 开始index,即 7 -2 = 5

 

二、defer
延迟处理
执行机制: 在函数内先实例(这在defer函数里包含函数参数有用,比如 defer func(int,int,func()),先执行里面的func),然后待执行完函数后,多个defer再按照
LIFO(后进先执行)原则执行。
还有一点需要注意,defer在实例时,它的参数是已确定,比如在defer前面定义了参数a = 1,在defer 后面再重新赋值a = 10,在执行defer时是按a=1传进defer的。

func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}

func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
fmt.Println("dfdff")
}

 

 

三、指针

&在变量前,取的是指针变量(即内存地址)

a := 10
b := &a //获取到a变量的内存地址,类型是 int的指针类型: *int
c := b //通过对指针变量进行取值操作,获取指针变量指向的原变量的值

关键字 new , make
new : func new(Type) *Type
在声明类型指针变量时,因为为引用类型,所以需要初始化后才有内存空间,才能进行赋值
var a *int
a = new(int)
*a = 10
fmt.Println(a)

make: func make(t Type, size ...IntegerType) Type
make只适用slice、map、chan
make函数是无可替代的,我们在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。
func main() {
var b map[string]int
b = make(map[string]int, 10)
b["沙河娜扎"] = 100
fmt.Println(b)
}
new与make的区别:
1、二者都是用来做内存分配的。
2、make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
3、而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

 

 

四、结构体(struct)
type 类型名 struct {
字段名 字段类型
字段名 字段类型

}
结构体本身也是一种类型,我们可以像声明内置类型一样使用var关键字声明结构体类型。
基本例子:

type person struct {
name string
city string
age int8
}

func main() {
	var p1 person
	p1.name = "沙河娜扎"
	p1.city = "北京"
	p1.age = 18
	fmt.Printf("p1=%v\n", p1)  //p1={沙河娜扎 北京 18}
	fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"沙河娜扎", city:"北京", age:18}
}

可以通过使用new关键字对结构体进行实例化,得到的是结构体的地址。 格式如下:
var p2 = new(person)
fmt.Printf("%T\n", p2)     //*main.person
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"", city:"", age:0}
p2是一个结构体
Go语言中支持对结构体指针直接使用.来访问结构体的成员。
var p2 = new(person)
p2.name = "小王子"
p2.age = 28
p2.city = "上海"
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"小王子", city:"上海", age:28}
p2.age = 28 其实在底层是(p2).age = 28,这是go语言帮助我们实现的语法糖。

  

 

五、构造函数
Go语言的结构体没有构造函数,我们可以自己实现。 例如,下方的代码就实现了一个person的构造函数。 因为struct是值类型,如果结构体比较复杂的话,值拷贝性能开销会比较大,所以该构造函数返回的是结构体指针类型。

func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}

调用构造函数
p9 := newPerson("张三", "沙河", 90)
fmt.Printf("%#v\n", p9) //&main.person{name:"张三", city:"沙河", age:90}

  

 

六、方法
方法是一种作用于特定类型变量的函数,类似其他语言的this或self,定义如下:
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
函数体
}
一般接收者变量名是接收类型的名字首位小写,如结构体Person,它的接收者名为p。
例子:

//Person 结构体
type Person struct {
name string
age int8
}

	//NewPerson 构造函数
	func NewPerson(name string, age int8) *Person {
		return &Person{
			name: name,
			age:  age,
		}
	}

	//Dream Person做梦的方法
	func (p Person) Dream() {
		fmt.Printf("%s的梦想是学好Go语言!\n", p.name)
	}

	func main() {
		p1 := NewPerson("小王子", 25)
		p1.Dream()
	}

 方法与函数的区别是,函数不属于任何类型,方法属于特定的类型。

 

七、channel

channel 是遵循FIFO原则,有个例子,当配合goroutine(开线程)使用,多个channel读取时,会实时根据当前读取的cha1,cha1存多少被读取的就有多少。

例子:

`package main

import(
"fmt"
"time"
)

func recv(ch chan int) {
for i := 0;i<3;i++ {
fmt.Println(i)
time.Sleep(time.Second)
ch <- i //传送值给cha1
}
close(ch)
fmt.Println("ppppppp")
}

func recv2(ch1 chan int,ch2 chan int) {
for {
tmp,ok := <-ch1
fmt.Println(tmp)
if !ok{
break
}
ch2 <- tmp*tmp
}
close(ch2)
fmt.Println("kkssk")
}

func main() {
cha1 := make(chan int, 100) //初始化一个channel
cha2 := make(chan int, 200) // 初始化另一个channel

go recv(cha1)
go recv2(cha1, cha2)

for tt := range cha2 {
	fmt.Println(tt)
}
}`

  

待续~

 

posted @ 2020-07-21 15:11  fengzao  阅读(192)  评论(0编辑  收藏  举报