Go学习笔记一
来源:互联网 发布:淘宝老酒拍卖真吗 编辑:程序博客网 时间:2024/05/16 10:31
- 变量类型和关键字
- 字符串
- 多行字符串
- 控制结构
- if
- goto
- for循环
- range迭代器
- switch
- 内建函数
- arrayslices 和 map
- array
- slice
- map
变量、类型和关键字
完整的整数类型列表(符号和无符号)是
int8 , int16 , int32 , int64 和 byte , uint8 , uint16 , uint32 ,uint64
混合用这些类型向变量赋值会引起编译器错误,例如下面的代码:
package mainfunc main() { var a int //← 通用整数类型 var b int32 //← 32 位整数类型 a = 15 b = a + a //← 混合这些类型是非法的 //cannot use a + a (type int) as type int32 in assignment println(b) b = b + 5 //← 5 是一个(未定义类型的)常量,所以这没问题 println(b)}
字符串
字符串在 Go 中是 UTF-8 的由双引号(”)包裹的字符序列。如果你使用单引号(’)则
表示一个字符(UTF-8 编码)——这种在 Go 中 不是 string。
一旦给变量赋值,字符串就不能修改了:在 Go 中字符串是不可变的。从 C 来的用户,
下面的情况在 Go 中是非法的。
var s string = "hello"s[0] = 'c' //← 修改第一个字符为 ’c’ ,这会报错
在 Go 中实现这个,需要下面的方法:
package main import "fmt"func main() { var s = "hello" var c = [] rune (s)//转换 s 为 rune 数组 c[0] = 'c'//修改第一个字符为 ’c’ var s2 = string (c)//创建 新的 字符串 s2 保存修改; fmt.Printf("%s\n", s2)}
多行字符串
基于分号的置入,你需要小心使用多行字符串。如果这样写:
s := "Starting part"+ "Ending part"
会被转换为:
s := "Starting part" ;+ "Ending part" ;
这是错误的语法,应当这样写:
//正确的方式一:s := "Starting part" +"Ending part"
正确的方式二:
Go 就不会在错误的地方插入分号。另一种方式是使用反引号 ` 作为 原始 字符串符号:
//正确的方式二:s := `Starting partEnding part`fmt.Printf("Value is: %v", s)//Printf() 的 %v 参数含义是用默格式打印这个值
控制结构
在 Go 中只有很少的几个控制结构例如这里没有 do 或者 while 循环,只有
for 。有(灵活的) switch 语句和 if ,而 switch 接受像 for 那样可选的初始化语句。还有叫做类型选择和多路通讯转接器的 select,语法有所不同(同 C 相比):
无需圆括号,而语句体必须 总是 包含在大括号内。
if
if x > 0 { //← { 是强制的 return y} else { return x}//===============//下面的语法在 Go 中是非法的:if err ! = nil{ // ← 必须同 if 在同一行 return err}
//if 和 switch 接受初始化语句,通常用于设置一个(局部)变量。if err := Chmod(0664) ; err ! = nil { //← nil 与 C 的 NULL 类似 fmt.Printf(err) //← err 的作用域被限定在 if 内 return err}
goto
Go 有 goto 语句——明智的使用它。用 goto 跳转到一定是当前函数内定义的标签。例如假设这样一个循环:
package main func main() { myfunc()}func myfunc() { i := 0Here: // ← 这行的第一个词,以分号结束作为标签,标签大小写敏感 println(i) i++ if i > 10 { //打印1 到 10 ,这里不加条件会是无限循环 return } goto Here// ← 跳转}
for循环
Go 的 for 循环有三种形式,只有其中的一种使用分号。
for init ; condition ; post { } //← 和 C 的 for 一样for condition { } //← 和 while 一样for { } //← 死循环
//由于 Go 没有逗号表达式,而 ++ 和 – 是语句而不是表达式,如果你想在 for 中//执行多个变量,应当使用 平行赋值。// Reverse afor i, j := 0, len (a)-1 ; i < j ; i, j = i+1, j-1 { a[i], a[j] = a[j], a[i] //← 平行赋值}
break 和 continue
循环嵌套循环时,可以在 break 后指定标签。用标签决定 哪个 循环被终止:
package main func main() { myfunc()}func myfunc() { for j := 0 ; j < 5 ; j++ { for i := 0 ; i < 10 ; i++ { if i > 2 { break //← 现在终止的是 j 循环,而不是 i 的那个 } println(i) } println(j) }}
//continuepackage main func main() { for i := 0 ; i < 10 ; i++ { if i > 5 { continue //← 跳过循环中所有的代码 println(i) } println(i) }}
range迭代器
range 是个迭代器,当被调用的时候,从它循环的内容中返回一个键值对
package main import "fmt"func main() { list := [] string { "a", "b", "c", "d", "e", "f" } for k, v := range list { // 对 k 和 v 做想做的事情 fmt.Printf("list[%d] = %s\n",k,v) }}// list[0] = a// list[1] = b// list[2] = c// list[3] = d// list[4] = e// list[5] = f
switch
可以使用 fallthrough 使其匹配失败后自动向下尝试。
没有 fallthrough :
switch i { case 0: // 空的 case 体 case 1: f() // 当 i == 0 时, f 不会被调用!}
而这样:
switch i { case 0: fallthrough case 1: f() // 当 i == 0 时, f 会被调用!}
用 default 可以指定当其他所有分支都不匹配的时候的行为。
switch i { case 0: case 1: f() default : g() // 当 i 不等于 0 或 1 时调用}
分支可以使用逗号分隔的列表。
package main // import "fmt"func main() { println(shouldEscape('?')) //true}func shouldEscape(c byte ) bool { switch c { case ' ', '?', '&', '=', '#', '+':// ← , as ”or” return true } return false}
内建函数
//Go 中的预定义函数close new panic complexdelete make recover reallen append print imagcap copy println
可以使用命令查看函数文档
go doc builtin // 获得关于内建类型和函数的在线文档。
查看某个函数文档
//获得copy的文档 go doc builtin copy
close//用于 channel 通讯。使用它来关闭 channel,delete//用于在 map 中删除实例。len 和 cap//可用于不同的类型, len 用于返回字符串、slice 和数组的长度。new//用于各种类型的内存分配。make//用于内建类型(map、slice 和 channel)的内存分配。copy//用于复制 slice。append//用于追加 slice。panic 和 recover//用于 异常 处理机制。print 和 println//是底层打印函数,可以在不引入 fmt 包的情况下使用。它们主要用于调试。complex 、 real 和 imag//全部用于处理 复数。
array、slices 和 map
array
array 由 [n]<type>
定义,n 标示 array 的长度,而 <type>
标示希望存储的内容的类型。对 array 的元素赋值或索引是由方括号完成的:
package main import "fmt"func main() { // var arr = [10] int 这样的数组类型有固定的大小。大小是类型的一部分 。由于不同的大小是不同的类型,因此不能改变大小 var arr [10] int arr[0] = 42 arr[1] = 13 fmt.Printf("The first element is %d\n", arr[0]) }
var arr = [10] int
这样的数组类型有固定的大小。大小是类型的一部分 。由于不同的大小是不同的类型,因此不能改变大小。数组同样是值类型的:将一个数组赋值给另一个数组,会 复制 所有的元素。尤其是当向函数内传递一个数组的时候,它会获得一个数组的副本,而不是数组的指针。
可以像这样声明一个数组:var a [3] int,如果不使用零来初始化它,则用复合声明: a := [3] int{ 1, 2, 3 }
也可以简写为 a := [...] int{ 1, 2, 3 }
,Go 会自动统计元素的个数。
//多维数组a := [3][2] int { [2] int { 1,2 } , [2] int { 3,4 } , [2] int { 5,6 } }
slice
slice 是一个 指向 array 的指针,这是其与 array 不同的地方;slice 是引用
类型,这意味着当赋值某个 slice 到另外一个变量,两个引用会指向同一个 array。
sl := make ([] int , 10)
//错误的示例,如果要扩展slice需要使用append和copypackage mainfunc main() { var array [100] int //← Create array, index from 0 to 99 slice := array[0:99] //← Create slice, index from 0 to 98 slice[98] = 'a'// ← OK slice[99] = 'a'// ← Error: ”throw: index out of range”}
使用append扩展slice
package mainimport "fmt"func main() { s0 := [] int { 0, 0 } s1 := append (s0, 2)//追加一个元素, s1 == []int{0, 0, 2} ; fmt.Printf("%v\n",s1) s2 := append (s1, 3, 5, 7)//追加多个元素, s2 == []int{0, 0, 2, 3, 5, 7} ; fmt.Printf("%v\n",s2) //...可变长参数 http://studygolang.com/articles/1965 s3 := append (s2, s0...)//追加一个 slice, s3 == []int{0, 0, 2, 3, 5, 7, 0, 0} 。注意这三个点! fmt.Printf("%v\n",s3)}// [0 0 2]// [0 0 2 3 5 7]// [0 0 2 3 5 7 0 0]
copy的使用
package mainimport "fmt"func main() { var a = [...] int { 0, 1, 2, 3, 4, 5, 6, 7 } var s = make ([] int , 6) n1 := copy (s, a[0:])// ← n1 == 6, s == []int{0, 1, 2, 3, 4, 5} fmt.Printf("%v\n",s) fmt.Printf("%v\n",n1) //copy返回拷贝的元素个数 n2 := copy (s, s[2:])// ← n2 == 4, s == []int{2, 3, 4, 5, 4, 5} fmt.Printf("%v\n",s) fmt.Printf("%v\n",n2)}
map
一般定义 map 的方法是: map[<from type>]<to type>
package mainimport "fmt"func main() { monthdays := map [ string ] int { "Jan": 31, "Feb": 28, "Mar": 31, "Apr": 30, "May": 31, "Jun": 30, "Jul": 31, "Aug": 31, "Sep": 30, "Oct": 31, "Nov": 30, "Dec": 31,// ← 逗号是必须的 } // monthdays := make ( map[ string ] int )//当只需要声明一个 map 的时候,使用 make 的形式 fmt.Printf("%d\n", monthdays["Dec"])//打印出 12 月的天数 year := 0 for _, days := range monthdays { //← 键没有使用,因此用 _, days year += days } fmt.Printf("Numbers of days in a year: %d\n", year) //向 map 增加元素,可以这样做: monthdays["Undecim"] = 30 //← 添加一个月 monthdays["Feb"] = 29 //← 闰年时重写这个元素 //检查元素是否存在的两种方式 //var value int var present bool //value, present = monthdays["Jan"] _, present = monthdays["Jan"] //← 如果存在, present 则有值 true println(present) //← 或者更接近 Go 的方式 //v, ok := monthdays["Jan"] _, ok := monthdays["Jan"]// ← “逗号 ok ”形式 println(ok) //也可以从 map 中移除元素: delete(monthdays, "Mar") //← 删除 ”Mar” 吧}
参考文章:
- Go学习笔记一
- Go学习笔记(一)
- GO语言学习笔记一
- GO语言学习笔记(一)
- Go学习笔记(一)
- GO 学习笔记(一)
- Go语言学习笔记(一) [Go语言的HelloWorld]
- Go学习笔记(一)初始Go以及环境安装
- GO 学习笔记 一基础篇
- Go语言学习笔记一、基础知识
- 《go语言编程》学习笔记一
- Go语言学习笔记(一)-环境准备
- Go语言学习笔记(一)程序结构
- Go语言学习笔记(一)
- 【Go学习笔记】Hello Go!
- go语言学习笔记(一)基础的基础篇
- Go语言并发与并行学习笔记(一)
- Go语言并发与并行学习笔记(一)
- mtk修改
- 报错:The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .c
- 一些服务的配置文件路径及常用linux命令
- hive大数据倾斜总结
- 【总结】PHP常见面试题汇总(二)
- Go学习笔记一
- 开发数据仓库模型的方法学(书摘备查)
- 【干货分享】流程DEMO-借款申请
- pod 使用中的一些报错
- hadoop环境搭建
- Java设计模式(20)行为型:状态模式
- 欢迎使用CSDN-markdown编辑器
- 仿百度文库在线浏览文档
- js跨域调用WebService的简单实例