Go学习笔记

Go

变量

变量声明

//1、单变量声明,类型放在变量名之后,可以为任意类型
var 变量名 类型
var v1,v2,v3 string //多变量同类型声明
//2、多变量声明
var {
    v1 int
    v2 []int
}

变量初始化

//1、使用关键字var,声明变量类型并赋值
var v1 int=10
//2、使用关键字var,直接对变量赋值,go可以自动推导出变量类型
var v2=10
//3、直接使用“:=”对变量赋值,不使用var,两者同时使用会语法冲突,推荐使用
v3:=10

匿名变量

//Go中所有声明后的变量都需要调用到,当出现函数多返回值,并且部分返回值不需要使用时,可以使用匿名变量丢弃该返回值
func GetName()(firstName,lastName,nickName string){
  return "May","Chan","Make"
}
_,_,nickName:=GetName()  //使用匿名变量丢弃部分返回值

指针

指针(pointer)在Go语言中可以被拆分为两个核心概念:

  • 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。(类似Java中的引用)
  • 切片,由指向起始元素的原始指针、元素数量和容量组成。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作)

取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

func main() {
	str := "test ptr"
	fmt.Println(&str) // &T  取变量T的内存地址值赋值到ptr  0xc000010200  返回的是指针类型
	fmt.Println(*&str) // *ptr 取指定内存地址对应的变量值 test ptr  返回的是值类型
}

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

  • 对变量进行取地址操作使用&操作符,可以获得这个变量的指针变量。
  • 指针变量的值是指针地址。
  • 对指针变量进行取值操作使用*操作符,可以获得指针变量指向的原变量的值。

通过指针修改数据

// 交换函数
func swap1(a, b *int) {
	// 取a指针的值, 赋给临时变量t
	t := *a
	// 取b指针的值, 赋给a指针指向的变量
	*a = *b
	// 将a指针的值赋给b指针指向的变量
	*b = t
}
func main() {
	// 准备两个变量, 赋值1和2
	x, y := 1, 2
	// 交换变量值
	swap1(&x, &y)
	// 输出变量值
	fmt.Println(x, y)
}

new() 函数可以创建一个对应类型的指针,创建过程会分配内存,被创建的指针指向默认值。

  func new(Type) *Type

	// new() 创建指针的另一种手段
	str := new(string)
	*str = "test new"
	fmt.Println(str)  // 0xc000010200
	fmt.Println(*str)

go和java类似,都是值传递,修改的是传入值的副本

type Person struct {
	name string
	age int
}

func updateAge(p Person){
	p.age = 10
}

func updateAgeByPtr(p *Person) {
	p.age = 10
}

func main() {
	p := Person{age: 0,name: "kevin"}
	fmt.Println(p.age)
	updateAge(p) // go中是值传递
	fmt.Println(p.age)
	updateAgeByPtr(&p)
	fmt.Println(p.age)
}

变量声明而没有赋值,默认为零值,不同类型零值不同,例如字符串零值为空字符串;

指针声明而没有赋值,默认为nil,即该指针没有任何指向。当指针没有指向的时候,不能对(*point)进行操作包括读取,否则会报空指针异常。

  var aPot *string
	fmt.Println(aPot)  // <nil>

指针也是一种类型,不同于一般类型,指针的值是地址,这个地址指向其他的内存,通过指针可以读取其所指向的地址所存储的值。
函数方法的接受者,也可以是指针变量。无论普通接受者还是指针接受者都会被拷贝传入方法中,不同在于拷贝的指针,其指向的地方都一样,只是其自身的地址不一样。

Go函数

Go函数中只关注匿名函数和闭包

所谓闭包就是函数的返回值是也是一个函数

// case1
func foo1(x *int) func() {
  // 返回值是一个函数
	return func() {
		*x = *x + 1
		fmt.Printf("foo1 val = %d\n", *x)
	}
}

// case2
func foo2(x int) func() {
	return func() {
		x = x + 1
		fmt.Printf("foo1 val = %d\n", x)
	}
}

func main() {

	x := 133
	f1 := foo1(&x)
	f1()
	fmt.Println(x)
	
	y := 100
	f2 := foo2(y)
	f2()
	fmt.Println(y)
}

执行结果:

foo1 val = 134
134
foo1 val = 101
100

case1和case2的区别在于值传递和引用传递的区别,go和Java一样只有值传递,这里所说的引用传递是传递的是地址的值

闭包的延迟绑定

只有在执行闭包函数的时候才会去寻找最新的函数环境

// case7  闭包的延迟绑定,
func foo7(x int) []func() {
	var fs []func()
	values := []int{1, 2, 3, 4, 5}
	for _, val := range values {
		fs = append(fs, func() {
			fmt.Printf("foo7 val = %d\n", x+val)
		})
	}
	return fs
}

func main()  {
	fs := foo7(11)
	for _, f := range fs{
		f()
	}
}

答案是:(在用到的时候去寻找函数的最新环境,此时是val 是 5)

foo7 val = 16
foo7 val = 16
foo7 val = 16
foo7 val = 16

Go面向对象

继承

在Go语言中,并没有显式的继承与显式的接口实现(接口实现其实也算是一种继承),Go对于继承,是通过组合来实现的

// 继承
type People struct {
	name string
	age int
}

type Teacher struct {
	People	// 以组合的方式引入
	teacherSomeThing string
}

接口

go中的接口不能有变量,go中实现接口是基于方法,如果一个类实现了这个接口中所有的方法,那么这个类就实现了这个接口

import "fmt"

// 只有实现了接口中的所有方法才是实现了这个接口
type Usb interface {
	start()
	stop()
}

type Usb1 interface {
	start()
	stop()
}

// computer既实现了Usb1也实现了Usb接口
type computer struct {

}

// 实现start
func (c computer)start()  {
	fmt.Println("调用start")
}

// 实现stop
func (c computer) stop()  {
	fmt.Println("调用stop")
}

func testUsb(u Usb)  {
	u.start()
	u.stop()
}

func main()  {
	c := computer{}
	testUsb(c)
}

从接口看go中的错误处理

// 内置的error接口,是一个常规的用于处理错误的接口。
// 其中 nil 表示没有错误。
type error interface {
    Error() string
}

实现自定义异常只需要实现这个error接口

type MyError struct {
	errorMsg string
}

func (error MyError) Error() string{
	return error.errorMsg
}

func main()  {
	myError := MyError{
		errorMsg : "catch error",
	}
	fmt.Println(myError.Error())
}

数据结构

链表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值