Go语言学习笔记这一堆主要是《Go语言编程》(人民邮电出版社)的读书笔记。中间会穿插一些零碎的点,比如源码学习之类的。大概就是这样吧。
1. 顺序编程
1.1 变量
变量的声明:
var 变量名 类型
var v1 int
也可以把若干变量的声明用大括号括起来
var {
v1 int
v2 string
}
变量初始化:
变量的初始化可以用如下的方法:
var v1 int = 10
var v2 = 10
v3 := 10
这三种方法的效果大体上是一样的。需要注意的有:第三种方法不能用于声明全局变量;以及:=赋值符号不能用于已声名过的变量名。
变量的赋值:
赋值这里唯一特别的是,Go语言支持多重赋值,比如交换i和j的值:
i, j = j, i
匿名变量:
Go语言有一个特性,就是在引入的包和变量在没有使用的时候,会在编译阶段报错。所以对于不需要的变量,可以使用匿名变量进行处理。
两个例子,第一个是多重返回函数的返回值的处理:
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
} _, _, nickName := GetName()
如果只需要函数的部分返回值的时候,就可以利用匿名变量。
第二个是for循环:
var a int[] = {5, 4, 3, 2, 1}
for _, value := range(a) {
balabala
}
当我们不需要range返回的部分结果的时候,就可以利用匿名变量。
1.2 常量
字面常量:大概只有一点要说,就是不需要额外做特别的声明。比如对于long类型的12,不存在12l这种写法。
常量定义:通过const关键字进行定义。
const Pi float64 = 3.1415926
需要注意的大概有:声明的时候可以不限定类型;常量定义的右值也可以是编译期运算的常量表达式。
const Zero = 0.0
const mask = 1 << 3
const Home = os.GetEnv("HOME")
这里第三句会导致错误。因为右值只有在运行期才能知道结果。
预定义常量:true,false,iota。
这里true和false没有什么说的。
iota可以被认为是一个可被编译器修改的常量,该常量在每一个const关键字出现的时候被重置为0。在下一个const出现之前,每出现一次iota,其所代表的数字自动加1。
Golang不支持enum关键字的枚举类型,通常把const和iota结合起来表示枚举,例如:
const {
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays
}
这样就将星期与整数对应了起来。
注意,numberOfDays并没有被导出。
1.3 类型
Golang支持以下类型:
基本类型:布尔型,整型,浮点型,复数型,字符串,字符型,错误型。
复合类型:指针,数组,切片,字典,通道,结构体,接口。
基本类型中,需要注意的问题如下;
int和int32在Golang中被认为是不同的两个类型。所以二者不能互相赋值(编译期不会自动做类型转换),需要进行强制的类型转换。
自动推导的浮点数类型是float64。
复数类型是其他大部分语言不支持的。例子如下:
var value1 complex64 value1 = 3.2 + 12i
value2 := 3.2 + 12i
value3 := complex(3.2, 12) x := real(value1)
y := imag(value1)
字符串可以用下表的方式获取其内容,但是字符串在初始化之后,其内容就不能进行修改了。
字符串的遍历,这还跟len()函数作用在字符串上的返回值有关,例子如下:
str := "Hello, 世界"
n := len(str) //n = 13
for i:=0, i<n, i++ {
fmt.Println(i, str[i])
} for i, ch := range str {
fmt.Println(i, ch)
} //该段代码输出了9行结果
另外需要注意的,range有两个返回值,第一个是下标,第二个是下标对应的值。
数组在声明了以后,就不能再修改其长度。
数组切片的实质可以理解成3部分:一个指向原数组的指针;数组切片中的元素个数;数组切片已分配的存储空间。
数组切片的声明方式如下:
//基于数组创建数组切片
var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var mySlice []int
mySlice = myArray[:] //基于所有数组元素创建切片
mySlice = myArray[:5] //基于数组的前5个(0~4)元素创建切片
mySlice = myArray[5:] //基于数组第5个开始(5~end)的元素创建切片 //直接创建数组切片
mySlice1 := make([]int, 5) //创建一个初始长度为5的数组切片,元素初始值是0
mySlice2 := make([]int, 5, 10) //除以上之外,预留了10个元素的存储空间
mySlice3 := []int{1, 2, 3, 4, 5} //直接创建并初始化一个包含5个元素的数组切片
append函数可以增加切片的元素。注意append函数并不是原地的。其应用例子如下:
mySlice := make([]int, 2, 10) mySlice = append(mySlice, 1)
mySlice = append(mySlice, 2, 3) mySlice2 := []int{4, 5}
mySlice = append(mySlice, mySlice2...)
注意最后的...,它将mySlice2的元素打散做为append的参数。
也可以通过数组切片来创建切片。例如:
oldSlice := make([]int, 5, 10)
newSlice1 := oldSlice[:3] //用oldSlice的前三个元素创建新的切片
newSlice2 := oldSlice[:7] //也可以超出原切片的数量,但是不能超过cap,超出的部分填0
copy函数可以将一个数组切片的内容复制到另一个数组切片。例如:
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{6, 7, 8} copy(slice2, slice1) //复制slice1的前三个元素到slice2
copy(slice1, slice2) //复制slice2到slice1的前三个位置
map的元素查找可以用以下方法:
myMap := make(map[string]int, 100) //声明一个map,cap为100 value, ok := myMap["1234"]
if ok { //找到了
//对value的处理
}
1.4 流程控制
条件语句if的例子如下:
if a < 5 {
return 0
} else {
return 1
}
需要注意的有:条件语句不需要括号;花括号必须存在;以及最重要的,不允许将最终的return包含在if...else...结构中。
选择语句switch的例子如下:
switch i {
case 0:
fmt.Println(0)
case 1:
fmt.Println(1)
fallthrough
case 3:
fmt.Println(3)
default:
fmt.Println("Default")
}
需要注意的有:除非明确的标明fallthrough,否则认为分支默认break;另外,switch后面的条件表达式也可以不设定,这时可以将switch看作是多个if...else...。
循环语句if的例子如下:
for i := 0; i < 10; i++ {
fmt.Println(i)
} j := 0
for j<10 {
fmt.Print(j)
j++
} k := 0
for {
fmt.Print(k)
k++
if k>10 {
break
}
}
总之,Golang是把for和while结合到了一起。同时,也有break和continue。break也可以选择中断哪个循环。
goto就是跳转到label。这个很少用,先写在这里。
1.5 函数
函数的定义和调用:
package mymath
import "errors" func Add(a int, b int) (ret int, err error) {
if a<0 || b<0 {
err = errors.New("Should be non-negative numbers!")
return
}
return a + b, nil
} c := mymath.Add(1, 2)
需要注意的有:函数、类型和变量的可见性是由其首字母的大小写来确定的,大写开头的是public,小写开头的是private;函数的返回值的变量名可以先声明出来,在函数体内对变量进行处理后直接return即可;函数可以同时返回多个值。
同时,Golang的函数也支持不定参数,例如:
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
} myfunc(2, 3, 4)
myfunc(1, 3, 7, 13) func myfunc2(args ...int) {
myfunc(args...)
myfunc(args[1:]...)
}
通过例子可以看到不定参数的函数的遍历方法和调用方法。以及作为变参函数嵌套的传参方法。我觉得最关键的是记住,...在跟类型一起出现的时候,表明的是变参类型;...在跟变量名一起出现的时候,表明是将该变量内容打散。这种记法与*和&的区别方法一致。
如果希望传递任意类型的不定参数,可以利用interface{}。这里先举一个例子,后面会再具体描述interface{}。
func MyPrintf(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "int")
case string:
fmt.Println(arg, "string")
default:
fmt.Println(arg, "unknown")
}
}
}
匿名函数简单的说就是没有函数名的函数。匿名函数可以赋值给一个变量名,也可以直接执行。例如:
f := func(x, y int) int {
return x + y
} func (ch chan int) {
ch <- ACK
} (reply_chan)
立即执行的匿名函数,需要把传入的参数放到函数后面的括号中。
这里还有一个闭包的概念,目前还没太懂,待补充。
错误处理,Golang提供了error,defer,panic和recover工具。
error是一个接口,其定义如下:
type error interface {
Error() string
}
对于需要返回错误的函数,多数情况下定义成下面的形式,并按以下方式调用:
func Foo(param int) (n int, err error) {
// ...
} n, err := Foo(0)
if err != nil {
// 错误处理
} else {
// 使用返回值n
}
那么,对于自定义的error类型(即实现了error接口的类型),通常定义的形式如下:
type PathError struct {
Op string
Path string
Err error
} func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
} func Stat (name string) (fi FileInfo, err error) {
var stat syscall.Stat_t err =syscall.Stat(name, &stat)
if err != nil {
return nil, &PathError{"stat", name, err}
} return fileInfoFromStat(&stat, name), nil
}
defer关键字主要是用来处理代码中需要在最后完成的任务,比如关闭管道,关闭文件等。例子如下:
func CopyFile(dst, src string) (w int64, err error) {
srcFile, err := os.Open(src)
if err != nil {
return
}
defer srcFile.Close()
return io.Copy(dstFile, srcFile)
}
另外,如果一个函数中有多个defer关键字,那么它们是以后进先出的方式(即自下而上的)执行。
panic和recover两个函数是Golang中用来处理异常的函数。其流程大致为:当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。recover()函数用于终止错误流程。一般情况下,recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程,会导致该goroutine所属的进程打印异常信息后直接退出。
常见的recover()调用方法如下:
defer func() {
if r := recover(); r != nil {
log.Printf("Runtime error caught: %v", r)
}
}()
这样写,无论函数中是否出发了错误处理流程,该匿名函数都将在函数退出时得到执行。
第一节大概是这样~如果有任何问题还会及时更新~~~
Go语言学习笔记(1)——顺序编程的更多相关文章
-
HTML语言学习笔记(会更新)
# HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...
-
孙鑫VC学习笔记:多线程编程
孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010 HQU Email:zgzhaobo@gmail.com QQ:452728574 Latest Modified ...
-
2017-04-21周C语言学习笔记
C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...
-
2017-05-4-C语言学习笔记
C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...
-
java学习笔记15--多线程编程基础2
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...
-
《C# 语言学习笔记》——目录
C# 简介 变量和表达式 流程控制 3.1 布尔逻辑 3.2 goto语句 3.3 分支 3.4 循环 变量的更多内容 4.1 类型转换 4.2 复杂的变量类型 4.3 字符串的处理 函数 5.1 定 ...
-
《C# 语言学习笔记》——C# 简介
1 什么是.NET Framework .NET Framework 是Microsoft为开发应用程序而创建的一个富有革命性的新平台. 1.1 .NET Framework 的内容 .NET Fra ...
-
Hadoop学习笔记(7) ——高级编程
Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...
-
WCF学习笔记之事务编程
WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...
随机推荐
-
Vim 强大的配置
新建文件.vimrc,然后复制如下内容,并将该文件放到vim安装目录下 map <F9> :call SaveInputData()<CR> func! SaveInputDa ...
-
简单的玩玩etimer <;contiki学习笔记之九>;
好吧,我承认etimer有点小复杂,主要是它似乎和contiki的process搅在一起,到处都在call_process.那就先搜搜contiki下的etimer的example看看,然后再试着写一 ...
-
【转】一个FAE(AE)的体会和大家交流
原文网址:http://www.52rd.com/bbs/dispbbs.asp?boardID=63&ID=228682 本人在国内某芯片设计公司工作近5年时间岗位是AE和FAE,两个工作量 ...
-
HTML5小游戏UI美化版
HTML5小游戏[是男人就下一百层]UI美化版 之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的. 结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下. 介绍 ...
-
简单聊聊java中如何判定一个对象可回收
背景 说到java的特性,其中一个最重要的特性便是java通过new在堆中分配给对象的内存,不需要程序员主动去释放,而是由java虚拟机自动的回收.这也是java和C++的主要区别之一:那么虚拟机是如 ...
-
2018.2.21 Python 初学习
折腾了一天,一直在用CMD学习Python写Hello World.偶然间发现可以用Pycharm.也算是给后面想学习的人提个醒,方便省事许多. format()使用方法. age = 20name ...
-
i3wm 调节音量
i3wm,设置调节音量的快捷键 configure file: ~/.config/i3/config add # for sound control bindsym XF86AudioRaiseVo ...
-
C语言struct小知识
1.C语言里的struct是不能包含成员函数的,只能有数据成员2.C语言struct定义变量只能用一下两种方式:struct { ... } x, y, z;struct point pt;直接poi ...
-
大数据入门第二十二天——spark(二)RDD算子(2)与spark其它特性
一.JdbcRDD与关系型数据库交互 虽然略显鸡肋,但这里还是记录一下(点开JdbcRDD可以看到限制比较死,基本是鸡肋.但好在我们可以通过自定义的JdbcRDD来帮助我们完成与关系型数据库的交互.这 ...
-
【noip模拟赛1】古韵之鹊桥相会(最短路)
描述 迢迢牵牛星,皎皎河汉女. 纤纤擢素手,札札弄机杼: 终日不成章,泣涕零如雨. 河汉清且浅,相去复几许? 盈盈一水间,脉脉不得语. ——<古诗十九首> 传说,上古时期的某个七月七日,王 ...