GoDoc-1.基础

1. 包

go是由包来组织的。
程序从main包的main函数开始。
使用引入的包时,以最后一个包名开始:

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    fmt.Println("My favorite number is", rand.Intn(10))//Println以fmt开始,Intn以rand开始
}

2. 包可见性

在go中一个方法或变量的开头字母大写,则这个方法或变量是可以被其他包引入的。否则不可以。

3. 函数

func swap(x, y string) (string, string) {//go可以返回多个值,参数可以写成x,y string形式
    return y, x
}
func split(sum int) (x, y int) { // 命名返回值
    x = sum * 4 / 9
    y = sum - x
    return
}

命名返回值即相当于x和y在函数开始定义,然后直接return返回。--这种用法容易造成歧义,不建议使用

4. 基本类型

bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // uint8 的别名

rune // int32 的别名
    // 表示一个 Unicode 码点

float32 float64 //浮点型

complex64 complex128 // 复数

int/uint/uintptr在32为系统占32位,在64位系统占64位。--Java的类型和系统无关,所以说Java是系统无关性的语言,而go不是。

当变量没有赋值时,则系统默认赋0值。数字型零值是0,布尔值零值是false,字符串零值是""

5. 类型转换

go里不允许隐式转换,必须显示转换
类型转换的语法--和Java不同

var a int = 123
float64 b = float64(a)

6. for

go里面唯一的循环就是for,go里没有while

for i := 0; i < 10; i++ { // 注意没有小括号,使用分号分隔
        sum += i
}

sum := 1
for sum < 1000 { // 当第一和第三个子句没有时,可以省略两个分号
    sum += sum
}

7. if

if x < 0 { // 也是没有小括号,大括号是必须的
    return sqrt(-x) + "i"
}

if v := math.Pow(x, n); v < lim { // 可以在判断语句之前有一个小的语句,但注意此时的v的作用域只在if语句块内(包括下面的else)
    return v
} else {
   return v
}

8. switch

var linux = "linux"
switch os := runtime.GOOS; os {
case "darwin":
    fmt.Println("OS X.")
case linux:
    fmt.Println("Linux.")
default:
    // freebsd, openbsd,
    // plan9, windows...
    fmt.Printf("%s.", os)
}

使用方式和Java几乎一样,但有两点不同:

  1. 每个case后系统自动加了break
  2. case中的东西可以不是常量且不一定是整数。

switch i {
case 0:
case f():
}

如果i的值为0,则f就不会执行


t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("Good morning!")
case t.Hour() < 17:
    fmt.Println("Good afternoon.")
default:
    fmt.Println("Good evening.")
}

switch可以没有条件,达到更好看的if-else if-else效果

9. defer

defer 语句会将函数推迟到外层函数返回之后执行。

推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用。

推迟的函数调用会被压入一个栈中。当外层函数返回时,被推迟的函数会按照后进先出的顺序调用。

func main() {
    fmt.Println("counting")

    for i := 0; i < 3; i++ {
        defer fmt.Println(i)
    }

    fmt.Println("done")
}

输出

counting done 2 1 0

10. 指针

var p *int
a := 123
p = &a
*p = 234

用法和C++中的几乎一样

11. 结构体

就是字段的集合

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    v.X = 4 // 使用.来访问
    p := &v
    p.X = 1e9 // 正常是(*p).X,但也可以直接使用指针p.X的方式。
    fmt.Println(v.X)
}

初始化一个结构体的方式:

type Vertex struct {
    X, Y int
}

var (
    v1 = Vertex{1, 2}  // has type Vertex
    v2 = Vertex{X: 1}  // Y:0 is implicit -- 这个还是比较新颖的
    v3 = Vertex{}      // X:0 and Y:0
    p  = &Vertex{1, 2} // has type *Vertex
)

12. 数组

var a [10]int
p := [10]int{1,2,3,4,5,6,7,8,9,10} // 数组的初始化

13. 切片

其实就是数组的一个引用。

var a []int //定义一个切片 此时 a == nil
primes := [6]int{2, 3, 5, 7, 11, 13}

var s []int = primes[1:4] //从下标1开始到下标4,包括1不包含4,总共4-1=3个元素
s[1] = 100 // 此时会修改primes数组的元素
println(primes)

切片并不存储任何数据,它只是描述了底层数组中的一段。
更改切片的元素会修改其底层数组中对应的元素。


q := []int{2, 3, 5, 7, 11, 13} //初始化一个切片

上述代码的含义就是创建一个长度6的数组,然后用一个切片p来指向它。


var a [10]int
以下切片是等价的:

a[0:10]
a[:10]
a[0:]
a[:]

即可以省略start和end,默认start=0,end=数组长度(最大下标+1)


切片的长度和容量

var a [10]int
var p []int = a[3:5]
len(p) // 长度 5-3=2
cap(p) //容量 3~10  10-3=7

长度就是切片包含的元素个数
容量就是切片对应的数组开始下标到数组结尾的元素个数


使用make来创建切片

a := make([]int, 5)  // len(a)=5 此时创建一个长度为5的数组,数组的每个元素为零值,然后返回这个数组的引用(切片)
b := make([]int, 0, 5) // len(b)=0, cap(b)=5 还可以指定长度和容量

切片可以是多维的

board := [][]string{
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }

向切片追加元素,使用内置append函数

func append(s []T, vs ...T) []T // 内置append函数
s = append(s, 2, 3, 4) //注意如果底层数组足够存放,则此函数会修改底层数组的值

当 s 的底层数组太小,不足以容纳所有给定的值时,它就会分配一个更大的数组。返回的切片会指向这个新分配的数组。


总结:创建一个切片的三种方法

var a []int = make([]int, 10) //创建即零值
var b []int = []int{1,2} //创建且赋初值
var c []int = p[1:3] //创建一个指向某个数组的引用

14. range

range和for在一起使用,可以遍历切片或映射的每个元素。

for i, v := range pow { //会返回下标和值
    fmt.Printf("2**%d = %d\n", i, v)
}
for _, v := range pow { // 只关心value
    fmt.Printf(" %d\n", v)
}
for i := range pow { //只关心下标
    fmt.Printf("%d\n", i)
}

15. 映射

就是Java中的Map

var m map[string]string // 此时 m == nil
创建map的两种方法:
m = make(map[string]string) //使用make
m["abc"] = "123"

var m = map[string]string{ //创建并初始化
    "abc" : "123",
    "def" : "456"
}

增加和修改元素都很简单,这里说一下删除和判无

delete(m, key) // 删除m映射中key的元素

elem = m[key] // 如果不存在则返回零值
elem, ok := m[key] //存在ok等于true,否则ok等于false

16. 函数参数值

函数本身其实和变量是一样的,可以当做参数

hypot := func(x, y float64) float64 { //可以把函数使用一个变量表示
        return math.Sqrt(x*x + y*y)
}
func compute(fn func(float64, float64) float64) float64 { //参数可以是一个函数
    return fn(3, 4)
}

甚至可以将函数当做另一个函数的返回值

func adder() func(int) int {
    return func(x int) int {
        return x + 1
    }
}
a := adder()
println(a(2))

17. 函数闭包

先看一下计算机科学上闭包的含义:

是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 3; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}

0 0
1 -2
3 -6
就是说sum这个变量随着函数返回一起存在,pos和neg分别对应两个函数以及函数一起存在的sum。
所以每次调用pos/neg都会使用之前的sum值。
其实这点有点类似于C++中的static变量--具有记忆性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容