忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 3074 | 回复: 3

[其他] Golang极简入门教程 [复制链接]

论坛徽章:
0
发表于 2015-05-25 13:08 |显示全部楼层
安装 Golang

http://golang.org/dl/ 可以下载到 Golang。安装文档:http://golang.org/doc/install

Hello Go

我们先创建一个文件 hello.go:

  1. package main

  2. import "fmt"

  3. func main() {
  4.     fmt.Printf("hello Golang\n");
  5. }
复制代码

执行此程序:


  1. go run hello.go
复制代码



Golang 程序由包(packages)组成,程序从 main 包开始运行:


  1. package main
复制代码

此语句表示此文件属于 main 包(多个源文件可以属于同一个包)。import 语句后接上包所在的路径(被叫做包路径或导入路径),一个目录中放置一个包,通常的做法是,目录名和包名相同:
  1. import (
  2.     "fmt"
  3.     "math/rand"
  4. )
复制代码

这里的 “fmt” 和 “math/rand” 为包路径(导入路径)。上面的 import 语句也可以这样写:
  1. import "fmt"
  2. import "math/rand"
复制代码

我们导入了包之后,就可以通过 “包名.name” 来引用导出的 name 了,例如:
import "fmt"

// fmt 包导出了 Printf
fmt.Printf("hello Golang\n");
在 Golang 中,一个名字如果首字母大写则表示此名字被导出。

函数

  1. package main

  2. import "fmt"

  3. func add(x int, y int) int {
  4.     return x + y
  5. }

  6. func main() {
  7.     fmt.Println(add(42, 13))
  8. }
复制代码


需要注意的就是,变量名在类型之前,这和很多语言都不一样。另外 x int, y int 也可以写为 x, y int:
  1. func add(x, y int) int {
  2.     return x + y
  3. }
复制代码

函数可以返回多个值:
  1. package main

  2. import "fmt"

  3. func swap(x, y string) (string, string) {
  4.     return y, x
  5. }

  6. func main() {
  7.     a, b := swap("hello", "world")
  8.     fmt.Println(a, b)
  9. }
复制代码

返回值可以被指定变量名,并且像变量一样使用:

  1. package main

  2. import "fmt"

  3. func split(sum int) (x, y int) {
  4.     x = sum * 4 / 9
  5.     y = sum - x
  6.     return
  7. }

  8. func main() {
  9.     fmt.Println(split(17))
  10. }
复制代码

可以看到 split 函数直接使用 return 语句而不用带参数。

变量

变量的声明使用 var 语句:


  1. var i int
  2. var c, python, java bool
复制代码

变量在声明时可以进行初始化:

  1. var x, y int = 1, 2
  2. var i, j = true, "hello"
复制代码

我们看到,初始化时可以指定也可以不指定变量类型。
按照 Golang 的语法,在函数外的任何结构(construct)都通过一个关键字开始,例如变量使用 var 关键字开始,函数使用 func 关键字开始。在函数内,变量赋值可以使用 := 操作符:

  1. package main

  2. func main() {
  3.     var x, y int = 1, 2
  4.     i, j := true, "hello"
  5. }
复制代码

:= 操作符左边为变量,右边为值。

数据类型

基本数据类型:

1.bool
2.string
3.int int8 int16 int32 int64
4.uint uint8 uint16 uint32 uint64
5.uintptr
6.byte(等价于 uint8)
7.rune(等价于 int32,用于表示一个 unicode code point)
8.float32 float64
9.complex64 complex128

类型转换使用表达式 T(v),含义为将 v 转换为类型 T:

  1. var i int = 42
  2. var f float64 = float64(i)

  3. i := 42
  4. f := float64(i)
复制代码

类型转换总需要显式的进行。

使用 const 来声明常量:


  1. const Pi = 3.14

  2. const (
  3.     Big = 1 << 100
  4.     Small = Big >> 99
  5. )
复制代码

控制语句

for 语句

Golang 使用(且只使用)for 来进行循环(没有 while 语句):


  1. package main

  2. func main() {
  3.     sum := 0
  4.    
  5.     for i := 0; i < 10; i++ {
  6.         sum += i
  7.     }
  8.    
  9.     // 这种写法等价于 C/C++ 等语言中的 while 语句
  10.     for sum < 1000 {
  11.         sum += sum
  12.     }
  13. }
复制代码

区别于 C/C++ 等语言,使用 for 语句时不需要 () 并且 {} 是必须的(后面谈到的 if、switch 在此语法处理上也是一样的)。如果需要无限循环,那么使用:

  1. for {
  2. }
复制代码

if 语句

if 语句可以在执行条件判断前带一个语句(这常被叫做 if 带上一个短语句),此语句中变量的生命周期在 if 语句结束后结束。例如:


  1. package main

  2. import (
  3.     "fmt"
  4.     "math/rand"
  5. )

  6. func main() {
  7.     if n := rand.Intn(6); n <= 2 {
  8.         fmt.Println("[0, 2]", n)
  9.     } else {
  10.         fmt.Println("[3, 5]", n)
  11.     }

  12.     // 这里开始无法使用变量 n
  13. }
复制代码

switch
  1. package main

  2. import (
  3.     "fmt"
  4.     "runtime"
  5. )

  6. func main() {
  7.     fmt.Print("Go runs on ")
  8.     // switch 类似 if 可以带上一个短语句
  9.     switch os := runtime.GOOS; os {
  10.     case "darwin":
  11.         fmt.Println("OS X.")
  12.     case "linux":
  13.         fmt.Println("Linux.")
  14.     default:
  15.         // freebsd, openbsd,
  16.         // plan9, windows...
  17.         fmt.Printf("%s.", os)
  18.     }
  19. }
复制代码

不像 C/C++ 等语言,Golang 中无需使用 break 语句来跳出 switch。另外,switch 可以没有条件:
  1. package main

  2. import (
  3.     "fmt"
  4.     "time"
  5. )

  6. func main() {
  7.     t := time.Now()
  8.     switch {
  9.     case t.Hour() < 12:
  10.         fmt.Println("Good morning!")
  11.     case t.Hour() < 17:
  12.         fmt.Println("Good afternoon.")
  13.     default:
  14.         fmt.Println("Good evening.")
  15.     }
  16. }
复制代码

defer
一个 defer 语句能够将一个函数调用加入一个列表中(这个函数调用被叫做 deferred 函数调用),在当前函数调用结束时调用列表中的函数。范例:

  1. func CopyFile(dstName, srcName string) (written int64, err error) {
  2.     src, err := os.Open(srcName)
  3.     if err != nil {
  4.         return
  5.     }
  6.     defer src.Close()

  7.     dst, err := os.Create(dstName)
  8.     if err != nil {
  9.         return
  10.     }
  11.     defer dst.Close()

  12.     return io.Copy(dst, src)
  13. }
复制代码

deferred 函数调用按先进后出的顺序执行:
  1. package main

  2. import "fmt"

  3. func main() {
  4.     for i := 0; i < 5; i++ {
  5.         // 输出 43210
  6.         defer fmt.Print(i)
  7.     }
  8. }
复制代码
结构(structs)
结构是一个域的集合:

  1. package main

  2. import "fmt"

  3. type Vertex struct {
  4.     X int
  5.     Y int
  6. }

  7. func main() {
  8.     v := Vertex{1, 2}
  9.     v.X = 4
  10.     fmt.Println(v)
  11. }
复制代码
Golang 中是存在指针的,但是指针不支持算术运算:
  1. p := Vertex{1, 2} // {1, 2} 为 struct literal
  2. q := &p // q 类型为 *Vertex
  3. q.X = 2 // 直接访问域 X
复制代码
就像上面看到的,struct 的 literal 由 {} 包裹,在 struct literal 中我们可以使用 Name: 这样的语法来为特定域设置值:
  1. type Vertex struct {
  2.     X, Y int
  3. }

  4. r := Vertex{X: 3} // 这时候 Y 为 0
复制代码
new 函数
我们可以通过表达式 new(T) 分配一个被初始化为 0 且类型为 T 的值,并且返回指向此值的指针,用法如下:

  1. var p *T = new(T)
  2. p := new(T)
复制代码
更详尽的例子:
  1. package main

  2. import "fmt"

  3. type Vertex struct {
  4.     X, Y int
  5. }

  6. func main() {
  7.     v := new(Vertex)
  8.     fmt.Println(v)
  9.     v.X, v.Y = 11, 9
  10.     fmt.Println(v)
  11. }
复制代码
数组和 slice
[n]T 在 Golang 中是一个类型(就像 *T 一样),表示一个长度为 n 的数组其元素类型为 T。范例:
  1. package main

  2. import "fmt"

  3. func main() {
  4.     var a [2]string
  5.     a[0] = "Hello"
  6.     a[1] = "World"
  7.     fmt.Println(a[0], a[1])
  8.     fmt.Println(a)
  9. }
复制代码
注意,数组长度无法被改变。
slice 是一个数据结构,其指向一个数组某个连续的部分。slice 用起来很像数组。[]T 为 slice 类型,其中元素类型为 T:
  1. package main

  2. import "fmt"

  3. func main() {
  4.     // 构建一个 slice
  5.     p := []int{2, 3, 5, 7, 11, 13}
  6.     fmt.Println("p ==", p)

  7.     for i := 0; i < len(p); i++ {
  8.         fmt.Printf("p[%d] == %d\n", i, p[i])
  9.     }
  10. }
复制代码

表达式 s[lo:hi] 用于创建一个 slice,新创建的 slice 的元素为 s 中 [lo, hi) 位置的元素。
创建 slice 使用 make 函数(而不是用 new 函数,因为需要设置额外的参数来控制 slice 的创建):

  1. // len(a) 为 5
  2. a := make([]int, 5)
复制代码
这里 make 函数会创建一个数组(其元素初始化为 0)并返回一个 slice 指向此数组。make 可以带第三个参数,用于指定容量:
  1. // len(b) 为 0
  2. // cap(b) 为 5
  3. b := make([]int, 0, 5)

  4. b = b[:cap(b)] // len(b)=5, cap(b)=5
  5. b = b[1:] // len(b)=4, cap(b)=4
复制代码
一个没有值的 slice 是 nil,长度和容量都为 0。
  1. package main

  2. import "fmt"

  3. func main() {
  4.     var z []int
  5.     fmt.Println(z, len(z), cap(z))
  6.     if z == nil {
  7.         fmt.Println("nil!")
  8.     }
  9. }
复制代码
range
range 被用在 for 中来迭代一个 slice 或者一个 map:

  1. package main

  2. import "fmt"

  3. var s = []int{1, 2, 3}

  4. func main() {
  5.     for i, v := range s {
  6.         fmt.Println(i, v)
  7.     }

  8.     // 只需要值,使用 _ 忽略索引
  9.     for _, v := range s {
  10.         fmt.Println(v)
  11.     }

  12.     // 只需要索引
  13.     for i := range s {
  14.         fmt.Println(i)
  15.     }
  16. }
复制代码
map
map 用于映射 key 到 value(值)。map 可以通过 make 来创建(而非 new):

  1. package main

  2. import "fmt"

  3. type Vertex struct {
  4.     Lat, Long float64
  5. }

  6. var m map[string]Vertex

  7. func main() {
  8.     m = make(map[string]Vertex)
  9.     m["Bell Labs"] = Vertex{
  10.         40.68433, -74.39967,
  11.     }
  12.     fmt.Println(m["Bell Labs"])
  13. }
复制代码
map iteral 很像 struct literal:

  1. var m = map[string]Vertex{
  2.     // 这里 Vertex 可以省略不写
  3.     "Bell Labs": Vertex{
  4.         40.68433, -74.39967,
  5.     },
  6.     "Google": Vertex{
  7.         37.42202, -122.08408,
  8.     },
  9. }
复制代码
使用 [] 来访问 map 中的值,使用 delete 来删除 map 中的值:

  1. m[key] = elem
  2. elem = m[key]
  3. delete(m, key)
复制代码
如果需要检查 map 中某 key 是否存在使用:
  1. elem, ok = m[key]
复制代码
elem 表示 key 的值(key 不存在时,elem 为 0),ok 表示 key 是否存在。
闭包
Golang 中函数也是一个值(就像 int 值一样),且函数可以是一个闭包。闭包是一个引用了外部变量的函数。看一个例子:

  1. package main

  2. import "fmt"

  3. func adder() func(int) int {
  4.     sum := 0
  5.     // 返回一个闭包,此闭包引用了外部变量 sum
  6.     return func(x int) int {
  7.         sum += x
  8.         return sum
  9.     }
  10. }

  11. func main() {
  12.     a := adder()
  13.     fmt.Println(a(9527))
  14. }
复制代码

论坛徽章:
0
发表于 2015-09-13 17:30 |显示全部楼层
谢谢楼主分享。来支持你了

论坛徽章:
6
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:582015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2016-10-10 16:32 |显示全部楼层
看完这些可以写简单的小程序了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

SACC2017购票7.8折优惠进行时

2017中国系统架构师大会(SACC2017)将于10月19-21日在北京新云南皇冠假日酒店震撼来袭。今年,大会以“云智未来”为主题,云集国内外顶级专家,围绕云计算、人工智能、大数据、移动互联网、产业应用等热点领域展开技术探讨与交流。本届大会共设置2大主会场,18个技术专场;邀请来自互联网、金融、制造业、电商等多个领域,100余位技术专家及行业领袖来分享他们的经验;并将吸引4000+人次的系统运维、架构师及IT决策人士参会,为他们提供最具价值的交流平台。
----------------------------------------
优惠时间:2017年8月2日前

活动链接>>
  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP