Go学习笔记一

来源:互联网 发布:淘宝老酒拍卖真吗 编辑:程序博客网 时间:2024/05/16 10:31

  • 变量类型和关键字
    • 字符串
    • 多行字符串
  • 控制结构
    • if
    • goto
    • for循环
    • range迭代器
    • switch
  • 内建函数
  • arrayslices 和 map
    • array
    • slice
    • map

变量、类型和关键字

完整的整数类型列表(符号和无符号)是

int8int16int32int64byteuint8uint16uint32uint64

混合用这些类型向变量赋值会引起编译器错误,例如下面的代码:

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 中删除实例。lencap//可用于不同的类型, len 用于返回字符串、slice 和数组的长度。new//用于各种类型的内存分配。make//用于内建类型(map、slice 和 channel)的内存分配。copy//用于复制 slice。append//用于追加 slice。panicrecover//用于 异常 处理机制。printprintln//是底层打印函数,可以在不引入 fmt 包的情况下使用。它们主要用于调试。complexrealimag//全部用于处理 复数。

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” 吧}

参考文章:

0 0
原创粉丝点击