go学习笔记(一)

栏目: Go · 发布时间: 5年前

内容简介:var num int;var num int = 1,var a,b int;var a,b int = 1,2;var a = 1;_,b=1,2;1,:=这个符号直接取代了var和type,这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;在函数外部使用则会无法编译通过,所以一般用var方式来定义全局变量。2,_(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。

var num int;var num int = 1,var a,b int;var a,b int = 1,2;var a = 1;_,b=1,2;

1,:=这个符号直接取代了var和type,这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;在函数外部使用则会无法编译通过,所以一般用var方式来定义全局变量。

2,_(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。

3,Go对于已声明但未使用的变量会在编译阶段报错

常量

const Pi=3.1415926;const i =10000;const MaxThread=10;const prefix ="astaxie_"

所谓常量,也就是在程序编译阶段就确定下来的值,而程序在运行时无法改变该值。在 Go 程序中,常量可定义为数值、布尔值或字符串等类型

整数类型有无符号和带符号两种。Go同时支持int和uint,这两种类型的长度相同,但具体长度取决于不同编译器的实现。Go里面也有直接定义好位数的类型:rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64。其中rune是int32的别称,byte是uint8的别称。

注: 这些类型的变量之间不允许互相赋值或操作,不然会在编译时引起编译器报错。另外,尽管int的长度是32 bit, 但int 与 int32并不可以互用。浮点数的类型有float32和float64两种(没有float类型),默认是float64。

Go中的字符串都是采用UTF-8字符集编码。字符串是用一对双引号("")或反引号(` `)括起来定义,它的类型是string。

注: 在Go中字符串是不可变的,若一定要修改,可以将字符串 s 转换为 []byte 类型,再转换回 string 类型,Go中可以使用+操作符来连接两个字符串,字符串虽不能更改,但可进行切片操作,如果要声明一个多行的字符串怎么办?可以通过`来声明。

array、slice、map

array就是数组,var arr [n]type,长度也是数组类型的一部分,因此[3]int与[4]int是不同的类型,数组也就不能改变长度。数组之间的赋值是值的赋值,即当把一个数组作为参数传入函数的时候,传入的其实是该数组的副本,而不是它的指针。如果要使用指针,那么就需要用到后面介绍的slice类型了。

“动态数组”,在Go里面这种数据结构叫slice,slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。slice可以从一个数组或一个已经存在的slice中再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i,类似于 python 的切片或者c++的vector。

从概念上面来说slice像一个结构体,这个结构体包含了三个元素:

一个指针,指向数组中slice指定的开始位置。

长度,即slice的长度。

最大长度,也就是slice开始位置到数组的最后位置的长度。

对于slice有几个有用的内置函数:

len 获取slice的长度

cap 获取slice的最大容量

append 向slice里面追加一个或者多个元素,然后返回一个和slice一样类型的slice

copy 函数copy从源slice的src中复制元素到目标dst,并且返回复制的元素的个数

注: append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。 但当slice中没有剩余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原数组的内容将保持不变;其它引用此数组的slice则不受影响。

注意: slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明slice时,方括号内没有任何字符。 slice是引用类型,所以当引用改变其中元素的值时,其它的所有引用都会改变该值。

map类似python中的字典。声明举例:var numbersmap [string]int,numbers =make(map[string]int)。

使用map过程中需要注意的几点:

map是无序的,每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取

map的长度是不固定的,也就是和slice一样,也是一种引用类型

内置的len函数同样适用于map,返回map拥有的key的数量

map的值可以很方便的修改,通过numbers["one"]=11可以很容易的把key为one的字典值改为11

map和其他基本型别不同,它不是thread-safe,在多个go-routine存取时,必须使用mutex lock机制

map的初始化可以通过key:val的方式初始化值,同时map内置有判断是否存在key的方式

通过delete删除map的元素:

map也是一种引用类型,如果两个map同时指向一个底层,那么一个改变,另一个也相应的改变

make、new操作

make用于内建类型(map、slice 和channel)的内存分配。new用于各种类型的内存分配。

注:new返回指针。make返回初始化后的(非零)值。make只能创建slice、map和channel。

流程控制

Go里面if条件判断语句中不需要括号,Go的if还有一个强大的地方就是条件判断语句里面允许声明一个变量,这个变量的作用域只能在该条件逻辑块内,其他地方就不起作用了,比如if x=1;x>0{执行体}。

goto类似 c语言 中的goto,

for,在循环里面有两个关键操作break和continue ,break操作是跳出当前循环,continue是跳过本次循环。当嵌套过深的时候,break可以配合标签使用,即跳转至标签所指定的位置, break和continue还可以跟着标号,用来跳到多重循环中的外层循环。

switch,类似与c的switch, Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch ,但是可以使用fallthrough强制执行后面的case代码。

注:函数可以返回多个值。Go函数支持变参,如 func myfunc(arg...int) {}。

传值 ,当我们传一个参数值到被调用函数里面时,实际上是传了这个值的一份copy,当在被调用函数中修改参数值的时候,调用函数中相应实参不会发生任何变化,因为数值变化只作用在copy上。

传指针使得多个函数能操作同一个对象。 传指针比较轻量级 (8bytes),只是传内存地址,我们可以用指针传递体积大的结构体。如果用参数值传递的话, 在每次copy上面就会花费相对较多的系统开销(内存和时间)。所以当你要传递大的结构体的时候,用指针是一个明智的选择。Go语言中channel,slice,map这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针。(注:若函数需改变slice的长度,则仍需要取地址传递指针)

defer, Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。

函数作为值、类型 。在Go中函数也是一种变量,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。函数当做值和类型在我们写一些通用接口的时候非常有用。

Panic和Recover

Panic是一个内建函数,可以中断原有的控制流程,进入一个panic状态中。当函数F调用panic,函数F的执行被中断,但是F中的延迟函数defer会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。panic可以直接调用panic产生。也可以由运行时错误产生,例如访问越界的数组。

Recover是一个内建的函数,可以让进入panic状态的goroutine恢复过来。recover仅在延迟函数defer中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷入panic状态,调用recover可以捕获到panic的输入值,并且恢复正常的执行。

main函数和init函数

Go里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main)。这两个函数在定义时不能有任何的参数和返回值。虽然一个package里面可以写任意多个init函数,但这无论是对于可读性还是以后的可维护性来说,我们都强烈建议用户在一个package中每个文件只写一个init函数。

Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。每个package中的init函数都是可选的,但package main就必须包含一个main函数。

程序的初始化和执行都起始于main包。如果main包还导入了其它的包,那么就会在编译时将它们依次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。下图详细地解释了整个执行过程:

go学习笔记(一)

import这个命令用来导入包文件,类似于include,

import . "fmt" 点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名

import f “fmt” 别名 fmt.Printf()->f.Printf()

import _ “fmt” _操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init函数。

struct类型

和C语言类似

定义:

type person struct {

name strin

gage int

}

1.按照顺序提供初始化值

P := person{"Tom", 25}

2.通过field:value的方式初始化,这样可以任意顺序

P := person{age:24, name:"Tom"}

3.当然也可以通过new函数分配一个指针,此处P的类型为*person

P := new(person)

匿名字段: Go支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段。当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct。通过匿名访问和修改字段相当的有用,但是不仅仅是struct字段哦,所有的内置类型(int string等)和自定义类型都是可以作为匿名字段的。

注:结构中匿名字段和结构本身字段重名,Go里面很简单的解决了这个问题,最外层的优先访问

面向对象

通俗的说就是给struct绑定了函数,函数接收者可以时值copy,也可以是指针,

method的语法如下:

func (r ReceiverType) funcName(parameters) (results)

在使用method的时候重要注意几点

虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样

method里面可以访问接收者的字段

调用method通过.访问,就像struct里面访问字段一样

method 重写,继承。

举例

package main

import "fmt"

type Human struct {

name  string

age  int

phone string // Human类型拥有的字段

}

type Student struct {

Human

school string

phone  string

}

type Employee struct {

Human      // 匿名字段Human

speciality string

phone      string // 雇员的phone字段

}

func (h Human) say() {

fmt.Println(h.name, h.age, h.phone)

}+++

func (h Employee) say() {

fmt.Println(h.name, h.age, h.phone, h.speciality, h.Human.phone)

}

func main() {

Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}

Tom := Student{Human{"Tom", 18, "123-456-189"}, "yichuan", "666"}

Tom.say()

Bob.say()

fmt.Println(Tom.phone, Tom.Human.phone)

注: 以上笔记基本来自

https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/preface.md

作为业余爱好仅仅记录了一些注意点


以上所述就是小编给大家介绍的《go学习笔记(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Art of Computer Programming, Volume 2

The Art of Computer Programming, Volume 2

Knuth, Donald E. / Addison-Wesley Professional / 1997-11-04 / USD 79.99

Finally, after a wait of more than thirty-five years, the first part of Volume 4 is at last ready for publication. Check out the boxed set that brings together Volumes 1 - 4A in one elegant case, and ......一起来看看 《The Art of Computer Programming, Volume 2》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具