• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Golang极简入门教程(一):基本概念

    安装 Golang

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

    Hello Go

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

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func main() {
        fmt.Printf("hello Golang\n");
    }

    执行此程序:

    复制代码 代码如下:

    go run hello.go

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

    复制代码 代码如下:

    package main

    此语句表示此文件属于 main 包(多个源文件可以属于同一个包)。import 语句后接上包所在的路径(被叫做包路径或导入路径),一个目录中放置一个包,通常的做法是,目录名和包名相同:

    复制代码 代码如下:

    import (
        "fmt"
        "math/rand"
    )

    这里的 “fmt” 和 “math/rand” 为包路径(导入路径)。上面的 import 语句也可以这样写:

    复制代码 代码如下:

    import "fmt"
    import "math/rand"

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

    复制代码 代码如下:

    import "fmt"
     
    // fmt 包导出了 Printf
    fmt.Printf("hello Golang\n");

    在 Golang 中,一个名字如果首字母大写则表示此名字被导出。

    函数

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func add(x int, y int) int {
        return x + y
    }
     
    func main() {
        fmt.Println(add(42, 13))
    }

    需要注意的就是,变量名在类型之前,这和很多语言都不一样。另外 x int, y int 也可以写为 x, y int:
    复制代码 代码如下:

    func add(x, y int) int {
        return x + y
    }

    函数可以返回多个值:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func swap(x, y string) (string, string) {
        return y, x
    }
     
    func main() {
        a, b := swap("hello", "world")
        fmt.Println(a, b)
    }

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

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func split(sum int) (x, y int) {
        x = sum * 4 / 9
        y = sum - x
        return
    }
     
    func main() {
        fmt.Println(split(17))
    }

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

    变量

    变量的声明使用 var 语句:

    复制代码 代码如下:

    var i int
    var c, python, java bool

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

    复制代码 代码如下:

    var x, y int = 1, 2
    var i, j = true, "hello"

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

    复制代码 代码如下:

    package main
     
    func main() {
        var x, y int = 1, 2
        i, j := true, "hello"
    }

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

    数据类型

    基本数据类型:

    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:

    复制代码 代码如下:

    var i int = 42
    var f float64 = float64(i)
     
    i := 42
    f := float64(i)

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

    使用 const 来声明常量:

    复制代码 代码如下:

    const Pi = 3.14
     
    const (
        Big = 1 100
        Small = Big >> 99
    )

    控制语句

    for 语句

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

    复制代码 代码如下:

    package main
     
    func main() {
        sum := 0
       
        for i := 0; i 10; i++ {
            sum += i
        }
       
        // 这种写法等价于 C/C++ 等语言中的 while 语句
        for sum 1000 {
            sum += sum
        }
    }

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

    复制代码 代码如下:

    for {
    }

    if 语句

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

    复制代码 代码如下:

    package main
     
    import (
        "fmt"
        "math/rand"
    )
     
    func main() {
        if n := rand.Intn(6); n = 2 {
            fmt.Println("[0, 2]", n)
        } else {
            fmt.Println("[3, 5]", n)
        }
     
        // 这里开始无法使用变量 n
    }

    switch

    复制代码 代码如下:

    package main
     
    import (
        "fmt"
        "runtime"
    )
     
    func main() {
        fmt.Print("Go runs on ")
        // switch 类似 if 可以带上一个短语句
        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)
        }
    }

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

    复制代码 代码如下:

    package main
     
    import (
        "fmt"
        "time"
    )
     
    func main() {
        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.")
        }
    }

    defer

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

    复制代码 代码如下:

    func CopyFile(dstName, srcName string) (written int64, err error) {
        src, err := os.Open(srcName)
        if err != nil {
            return
        }
        defer src.Close()
     
        dst, err := os.Create(dstName)
        if err != nil {
            return
        }
        defer dst.Close()
     
        return io.Copy(dst, src)
    }

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

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func main() {
        for i := 0; i 5; i++ {
            // 输出 43210
            defer fmt.Print(i)
        }
    }

    结构(structs)

    结构是一个域的集合:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    type Vertex struct {
        X int
        Y int
    }
     
    func main() {
        v := Vertex{1, 2}
        v.X = 4
        fmt.Println(v)
    }

    Golang 中是存在指针的,但是指针不支持算术运算:

    复制代码 代码如下:

    p := Vertex{1, 2} // {1, 2} 为 struct literal
    q := p // q 类型为 *Vertex
    q.X = 2 // 直接访问域 X

    就像上面看到的,struct 的 literal 由 {} 包裹,在 struct literal 中我们可以使用 Name: 这样的语法来为特定域设置值:

    复制代码 代码如下:

    type Vertex struct {
        X, Y int
    }
     
    r := Vertex{X: 3} // 这时候 Y 为 0

    new 函数

    我们可以通过表达式 new(T) 分配一个被初始化为 0 且类型为 T 的值,并且返回指向此值的指针,用法如下:

    复制代码 代码如下:

    var p *T = new(T)
    p := new(T)

    更详尽的例子:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    type Vertex struct {
        X, Y int
    }
     
    func main() {
        v := new(Vertex)
        fmt.Println(v)
        v.X, v.Y = 11, 9
        fmt.Println(v)
    }

    数组和 slice

    [n]T 在 Golang 中是一个类型(就像 *T 一样),表示一个长度为 n 的数组其元素类型为 T。范例:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func main() {
        var a [2]string
        a[0] = "Hello"
        a[1] = "World"
        fmt.Println(a[0], a[1])
        fmt.Println(a)
    }

    注意,数组长度无法被改变。

    slice 是一个数据结构,其指向一个数组某个连续的部分。slice 用起来很像数组。[]T 为 slice 类型,其中元素类型为 T:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func main() {
        // 构建一个 slice
        p := []int{2, 3, 5, 7, 11, 13}
        fmt.Println("p ==", p)
     
        for i := 0; i len(p); i++ {
            fmt.Printf("p[%d] == %d\n", i, p[i])
        }
    }

    表达式 s[lo:hi] 用于创建一个 slice,新创建的 slice 的元素为 s 中 [lo, hi) 位置的元素。

    创建 slice 使用 make 函数(而不是用 new 函数,因为需要设置额外的参数来控制 slice 的创建):

    复制代码 代码如下:

    // len(a) 为 5
    a := make([]int, 5)

    这里 make 函数会创建一个数组(其元素初始化为 0)并返回一个 slice 指向此数组。make 可以带第三个参数,用于指定容量:

    复制代码 代码如下:

    // len(b) 为 0
    // cap(b) 为 5
    b := make([]int, 0, 5)
     
    b = b[:cap(b)] // len(b)=5, cap(b)=5
    b = b[1:] // len(b)=4, cap(b)=4

    一个没有值的 slice 是 nil,长度和容量都为 0。

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func main() {
        var z []int
        fmt.Println(z, len(z), cap(z))
        if z == nil {
            fmt.Println("nil!")
        }
    }

    range

    range 被用在 for 中来迭代一个 slice 或者一个 map:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    var s = []int{1, 2, 3}
     
    func main() {
        for i, v := range s {
            fmt.Println(i, v)
        }
     
        // 只需要值,使用 _ 忽略索引
        for _, v := range s {
            fmt.Println(v)
        }
     
        // 只需要索引
        for i := range s {
            fmt.Println(i)
        }
    }

    map

    map 用于映射 key 到 value(值)。map 可以通过 make 来创建(而非 new):

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    type Vertex struct {
        Lat, Long float64
    }
     
    var m map[string]Vertex
     
    func main() {
        m = make(map[string]Vertex)
        m["Bell Labs"] = Vertex{
            40.68433, -74.39967,
        }
        fmt.Println(m["Bell Labs"])
    }

    map iteral 很像 struct literal:

    复制代码 代码如下:

    var m = map[string]Vertex{
        // 这里 Vertex 可以省略不写
        "Bell Labs": Vertex{
            40.68433, -74.39967,
        },
        "Google": Vertex{
            37.42202, -122.08408,
        },
    }

    使用 [] 来访问 map 中的值,使用 delete 来删除 map 中的值:

    复制代码 代码如下:

    m[key] = elem
    elem = m[key]
    delete(m, key)

    如果需要检查 map 中某 key 是否存在使用:
    复制代码 代码如下:

    elem, ok = m[key]

    elem 表示 key 的值(key 不存在时,elem 为 0),ok 表示 key 是否存在。

    闭包

    Golang 中函数也是一个值(就像 int 值一样),且函数可以是一个闭包。闭包是一个引用了外部变量的函数。看一个例子:

    复制代码 代码如下:

    package main
     
    import "fmt"
     
    func adder() func(int) int {
        sum := 0
        // 返回一个闭包,此闭包引用了外部变量 sum
        return func(x int) int {
            sum += x
            return sum
        }
    }
     
    func main() {
        a := adder()
        fmt.Println(a(9527))
    }

    您可能感兴趣的文章:
    • golang分层测试之http接口测试入门教程
    • golang编程入门之http请求天气实例
    • Golang极简入门教程(四):编写第一个项目
    • Golang极简入门教程(三):并发支持
    • Golang极简入门教程(二):方法和接口
    • golang特有程序结构入门教程
    上一篇:在Golang中使用C语言代码实例
    下一篇:Golang极简入门教程(二):方法和接口
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Golang极简入门教程(一):基本概念 Golang,极简,入门教程,一,