博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
搞定Go语言之第四天
阅读量:3961 次
发布时间:2019-05-24

本文共 5866 字,大约阅读时间需要 19 分钟。

指针

任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

地址:就是内存地址(用字节来描述的内存地址)指针:指针是带类型的。

&和*

&:表示取地址*:根据地址取值

定义一个变量:

var a int

取变量a的内存地址:

b := &a

取地址对应的值:

fmt.Println(*b)

定义一个修改数组第一个元素为100的函数:

func modifyArray(a1 [3]int) {	a1[0] = 100 //只是修改的内部的a1这个数组}

定义一个修改数组第一个元素为100的函数,接收的参数是一个数组的指针

func modifyArray2(a1 *[3]int) {	// (*a1)[0] = 100 //只是修改的内部的a1这个数组	//语法糖:因为Go语言中指针不支持修改	a1[0] = 100 //只是修改的内部的a1这个数组}

new和make

二者都是内存的分配(堆上),但是make只用于slice、map以及channel的初始化(非零值);

而new用于类型的内存分配,并且内存置为零。所以在我们编写程序的时候,就可以根据自己的需要很好的选择了。

make返回的还是这三个引用类型本身;而new返回的是指向类型的指针。

new()

该方法的参数要求传入一个类型,而不是一个值,它会申请一个该类型大小的内存空间,并会初始化为对应的零值,返回指向该内存空间的一个指针。如下:

func new(Type) *Type

make()

make也是用于内存分配,但是和new不同,它只用于slice、map和channel的内存创建,它返回的类型就是类型本身,而不是它们的指针类型。

func make(t Type, size ...IntegerType) Type

案例:

package mainimport "fmt"func main() {
// 以下是错误的写法 // var a *int //a是一个int类型的指针 // var b *string // var c *[3]int // 以上是错误的写法 var a = new(int) //得到一个int类型的指针 fmt.Println(a) *a = 10 fmt.Println(a) fmt.Println(*a) var c = new([3]int) fmt.Println(c) c[0] = 1 fmt.Println(*c)}

panic和recover

其实,Go语言是不支持 try…catch…finally 这种异常处理的,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。

在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,才使用Go中引入的Exception处理:defer, panic, recover。

panic:运行时异常

panic用法挺简单的, 其实就是throw exception。

panic是golang的内建函数,panic会中断函数F的正常执行流程, 从F函数中跳出来, 跳回到F函数的调用者. 对于调用者来说, F看起来就是一个panic, 所以调用者会继续向上跳出, 直到当前goroutine返回. 在跳出的过程中, 进程会保持这个函数栈. 当goroutine退出时, 程序会crash。

要注意的是, F函数中的defered函数会正常执行, 按照上面defer的规则。

同时引起panic除了我们主动调用panic之外, 其他的任何运行时错误, 例如数组越界都会造成panic

panic用法:

package mainimport (    "fmt")func main() {
test()}func test() {
defer func() {
fmt.Println("打印前") }() defer func() {
fmt.Println("打印中") }() defer func() {
fmt.Println("打印后") }() panic("触发异常") fmt.Println("test")}-------output-------打印后 打印中 打印前 panic: 触发异常 goroutine 1 [running]: main.test()     D:/Go_Path/go/src/logDemo/main.go:15 +0x98     main.main() D:/Go_Path/go/src/logDemo/main.go:8 +0x27 exit status 2```**recover:用来将函数在panic时恢复回来,用于做一些资源回收的操作**recover也是golang的一个内建函数, 其实就是try catch。不过需要注意的是:  1. recover如果想起作用的话, 必须在defered函数中使用。  2. 在正常函数执行过程中,调用recover没有任何作用, 他会返回nil。如这样:fmt.Println(recover()) 。  3. 如果当前的goroutine panic了,那么recover将会捕获这个panic的值,并且让程序正常执行下去。不会让程序crash。**recover 用法:**```gofunc main() {
fmt.Println("c") defer func() {
// 必须要先声明defer,否则不能捕获到panic异常 fmt.Println("d") if err := recover(); err != nil {
fmt.Println(err) // 这里的err其实就是panic传入的内容 } fmt.Println("e") }() f() //开始调用f fmt.Println("f") //这里开始下面代码不会再执行}func f() {
fmt.Println("a") panic("异常信息") fmt.Println("b") //这里开始下面代码不会再执行}-------output-------cad异常信息e

结构体(struct)和方法

type关键字用来在Go语言中定义新的类型。

创造一个新类型

type NewInt int

类型别名(软链)

var MyInt = int

byte: uint8 和 rune:int32是Go语言内置的别名。

类型别名只在代码编写过程中生效,编译完不存在。

结构体的定义

//结构体    // 创在新的类型要使用type关键字    type student struct {
name string age int gender string hobby []string } func main() {
var haojie = student{
name: "豪杰", age: 19, gender: "男", hobby: []string{
"篮球", "足球", "双色球"}, } //结构体支持.访问属性 fmt.Println(haojie) fmt.Println(haojie.name) fmt.Println(haojie.age) fmt.Println(haojie.gender) fmt.Println(haojie.hobby) }

结构体的实例化

var haojie = student{
name: "豪杰", age: 19, gender: "男", hobby: []string{
"篮球", "足球", "双色球"}, }

结构体支持.访问属性

fmt.Println(haojie)	fmt.Println(haojie.name)	fmt.Println(haojie.age)	fmt.Println(haojie.gender)	fmt.Println(haojie.hobby)

实例化方法1

// struct是值类型的	// 如果初始化时没有给属性(字段)设置对应的初始值,那么对应属性就是其类型的默认值	var wangzhan = student{
} fmt.Println(wangzhan.name) fmt.Println(wangzhan.age) fmt.Println(wangzhan.gender) fmt.Println(wangzhan.hobby)

实例化方法2 new(T) T:表示类型或结构体

var yawei = new(student)	fmt.Println(yawei)	// (*yawei).name	yawei.name = "亚伟"	yawei.age = 18	fmt.Println(yawei.name, yawei.age)	// 实例化方法3	var nazha = &student{
} fmt.Println(nazha) nazha.name = "沙河娜扎" fmt.Println(nazha.name)

结构体初始化

var stu1 = student{
"豪杰", 18, "男", []string{
"男人", "女人"}, } fmt.Println(stu1.name, stu1.age) //键值对初始化 var stu2 = &student{
name: "豪杰", gender: "男", } fmt.Println(stu2.name, stu2.age, stu2.gender)}

结构体的内存布局

// 内存是以字节为单位的十六进制数// 1字节 = 8位 = 8bitfunc main() {
type test struct {
a int16 b int16 c int16 } var t = test{
a: 1, b: 2, c: 3, } fmt.Println(&(t.a)) fmt.Println(&(t.b)) fmt.Println(&(t.c))}

方法

方法就是某个具体的类型才能调用的函数,Go的方法是在函数前面加上一个接收者。

type people struct {
name string gender string}//函数指定接受者之后就是方法// 在go语言中约定成俗不用this也不用self,而是使用后面类型的首字母的小写func (p *people) dream() {
p.gender = "男" fmt.Printf("%s的梦想是不用上班也有钱拿!\n", p.name)}func main() {
var haojie = &people{
name: "豪杰", gender: "爷们", } // (&haojie).dream() haojie.dream() fmt.Println(haojie.gender)}
package mainimport "fmt"// 可以给任意类型追加方法// 不能给别的包定义的类型添加方法type MyInt intfunc (m *MyInt) sayHi() {
fmt.Println("Hello MyInt~")}func main() {
var a MyInt fmt.Println(a) a.sayHi()}

构造函数

func newStudent(n string, age int, g string, h []string) *student {
return &student{
name: n, age: age, gender: g, hobby: h, }

结构体的嵌套

package mainimport "fmt"// 结构体内嵌模拟“继承”type animal struct {
name string}//定义一个动物会动的方法func (a *animal) move() {
fmt.Printf("%s会动~\n", a.name)}//定义一个狗的结构体type dog struct {
feet int animal}//定义了一个狗的方法 wangwangfunc (d *dog) wangwang() {
fmt.Printf("%s 在叫:汪汪汪~\n", d.name)}func main() {
var a = dog{
feet: 4, animal: animal{
name: "旺财", }, } a.wangwang() //调用狗的方法 a.move() //调用动物的方法}

结构体的匿名字段

package mainimport "fmt"// 匿名字段type student struct {
name string string int}func main() {
var stu1 = student{
name: "豪杰", } fmt.Println(stu1.name) fmt.Println(stu1.string) fmt.Println(stu1.int)}

转载地址:http://dzhzi.baihongyu.com/

你可能感兴趣的文章
快速打开菜单附件中的工具
查看>>
Windows系统进程间通信
查看>>
linux exec的用法
查看>>
C语言中如何使用宏
查看>>
Http与RPC通信协议的比较
查看>>
Source Insight的对齐问题
查看>>
ubuntu设置开机默认进入字符界面方法
查看>>
chrome 快捷键
查看>>
Linux下buffer和cache的区别
查看>>
程序员不应该再犯的五大编程错误
查看>>
utf8中文编码范围
查看>>
oracle中文(utf8)按拼音排序的简单解决方案
查看>>
[转载][转帖]Hibernate与Sleep的区别
查看>>
Linux系统的默认编码设置
查看>>
Linux系统调用
查看>>
Linux 信号signal处理机制
查看>>
Linux 信号signal处理函数
查看>>
perror简介
查看>>
signal( SIGINT, SigIntHandler )
查看>>
linux signal 处理
查看>>