zoukankan      html  css  js  c++  java
  • Go语言学习要点总结

    包##

    Go语言程序是通过package来组织的。例如最简单的HelloWorld程序:

    package main
    import "fmt"
    func main() {
        fmt.Printf("hello world");
    }
    

    其中package <pkgname>这一行告诉我们当前文件属于哪个包,这里的main则表示它是一个可以独立运行的包,名为main的包在编译之后会产生可执行文件,其他的包最后都会生成pkgname.a文件。

    要使用其他包中的函数,则需要导入该包,即例中的import fmt,包中有很多导出函数,当要使用包中的函数时,使用pkgName.funcName语法即可。

    值得一提的时,Go语言通过首字母的大小写来控制包中的变量或者函数是否导出,大写表示可以导出,小写表示包的私有数据。而不是依靠像public,private这样的关键字,Go的核心理念是简洁。


    变量声明##

    Go语言的变量声明采用了类型在后的方式,例如:
    var var1 int声明了一个int类型的变量,var关键字是Go最基本的定义变量方式。
    Go语言能够自动推导变量类型,这意味着,如果在变量声明的时候,同时赋值的话,可以直接这样写:

    a := 1      // 定义一个int型变量a
    b := 1.0    // 定义一个float型变量b
    

    多返回值函数##

    Go语言的函数支持多返回值,例如:

     func Swap(a int, b int) (int, int) {
        return b, a
     }
    

    如果给返回值指定了名字,也可用以下写法:

    func SumAndProduct(a int, b int) (s int, p int) {
        s = a + b
        p = a * b
        return  // 不用写出返回值
    }
    

    需要注意的一点是:Go语言强制了{必须和语句在同一行。


    method##

    通过method,Go语言也可以支持面向对象,method语法如下:
    func (r ReceiveType) funcName(parameters) (results)
    上面的语法表示funcName函数是附属在类型ReceiveType上的,下面给出一个简单的例子:

    package main
    import (
        "fmt"
        "math"
    )
    
    type Rectangle struct {
        width, height float64
    }
    
    type Circle struct {
        radius float64
    }
    
    func (r Rectangle) area() float64 {
        return r.width * r.height
    }
    
    func (c Circle) area() float64 {
        return c.radius * c.radius * math.Pi
    }
    
    func main() {
        r1 := Rectangle{12, 2}
        r2 := Rectangle{9, 4}
        c1 := Circle{10}
        c2 := Circle{25}
    
        fmt.Println("Area of r1 is: ", r1.area())
        fmt.Println("Area of r2 is: ", r2.area())
        fmt.Println("Area of c1 is: ", c1.area())
        fmt.Println("Area of c2 is: ", c2.area())
    }
    
    • method可以访问接收者的字段
    • 通过.方式调用method
    • method支持继承,这里就不展开了

    Interface##

    如果说method提供了Go语言面向对象的支持,那么interface则是某种意义上Go对泛型编程的支持。

    那么究竟什么是interface呢?简单来说interface就是一组method的组合,我们通过interface的来定义对象的一组行为。下面的例子演示了语法:

    package main
    import "fmt"
    
    type Human struct {
        name string
        age int
        phone string
    }
    
    type Student struct {
        Human //匿名字段
        school string
        loan float32
    }
    
    type Employee struct {
        Human //匿名字段
        company string
        money float32
    }
    
    //Human实现SayHi方法
    func (h Human) SayHi() {
        fmt.Printf("Hi, I am %s you can call me on %s
    ", h.name, h.phone)
    }
    
    //Human实现Sing方法
    func (h Human) Sing(lyrics string) {
        fmt.Println("La la la la...", lyrics)
    }
    
    //Employee重载Human的SayHi方法
    func (e Employee) SayHi() {
        fmt.Printf("Hi, I am %s, I work at %s. Call me on %s
    ", e.name,
            e.company, e.phone)
        }
    
    // Interface Men被Human,Student和Employee实现
    // 因为这三个类型都实现了这两个方法
    type Men interface {
        SayHi()
        Sing(lyrics string)
    }
    
    func main() {
        mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
        paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
        sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
        Tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}
    
        //定义Men类型的变量i
        var i Men
    
        //i能存储Student
        i = mike
        fmt.Println("This is Mike, a Student:")
        i.SayHi()
        i.Sing("November rain")
    
        //i也能存储Employee
        i = Tom
        fmt.Println("This is Tom, an Employee:")
        i.SayHi()
        i.Sing("Born to be wild")
    
        //定义了slice Men
        fmt.Println("Let's use a slice of Men and see what happens")
        x := make([]Men, 3)
        //这三个都是不同类型的元素,但是他们实现了interface同一个接口
        x[0], x[1], x[2] = paul, sam, mike
    
        for _, value := range x{
            value.SayHi()
        }
    }
    

    Go规定如果某个对象实现了某个接口的所有方法,此对象就实现了此接口。即所谓的duck-typing:当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子"。

    上面的例子定义了接口Men,由于Student和Employee都实现了Men中的所有方法,Student和Employee就实现了Men接口。我们就能用一个Men类型的变量存储Student和Employee对象。

    注:因为Student和Employee都包含一个匿名的Human字段,那么它们默认就已经实现了Human中的方法(继承),但是可以通过例子中的方式对该方法进行重写。

    空interface###

    空interface(interface{})不包含任何的method,正因为如此,所有的类型都实现了空interface。空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。例如:

    // 定义a为空接口
    var a interface{}
    var i int = 5
    s := "Hello world"
    // a可以存储任意类型的数值
    a = i
    a = s
    

    并发##

    Go语言最大的亮点在于,它在语言层面就支持了并行。这就是goroutine语法。

    goroutine是Go并行设计的核心。goroutine说到底其实就是线程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。

    如何使用goroutine可见下例:

    package main
    
    import (
        "fmt"
        "runtime"
    )
    
    func say(s string) {
        for i := 0; i < 5; i++ {
            runtime.Gosched()
            fmt.Println(s)
        }
    }
    
    func main() {
        go say("world") //开一个新的Goroutines执行
        say("hello") //当前Goroutines执行
    }
    
    // 以上程序执行后将输出:
    // hello
    // world
    // hello
    // world
    // hello
    // world
    // hello
    // world
    // hello
    

    经常与goroutine搭配使用的还有channel,channel有点类似Unix shell中的双向管道,可以通过它收发数据,这些值必须是特定的类型:channel类型。主要是为了解决goroutines之间的同步问题。

    默认情况下,channel接收和发送数据都是阻塞的,除非另一端已经准备好,这样就使得Goroutines同步变的更加的简单,而不需要显式的lock。所谓阻塞,也就是如果读取(value := <-ch)它将会被阻塞,直到有数据接收。其次,任何发送(ch<-5)将会被阻塞,直到数据被读出。无缓冲channel是在多个goroutine之间同步很棒的工具。

    当然Go也支持channel的缓冲大小,即channel可以存储多少元素。例如ch := make(chan bool, 4),创建了可以存储4个元素的bool型channel。在这个channel 中,前4个元素可以无阻塞的写入。当写入第5个元素时,代码将会阻塞,直到其他goroutine从channel 中读取一些元素,腾出空间。

    闭包##

    Go语言支持闭包,详见博文闭包

  • 相关阅读:
    51nod 1574 排列转换(猜结论)
    百度之星资格赛 1005 寻找母串(分块打表+组合数计算)
    百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)
    百度之星资格赛 1003 度度熊与邪恶大魔王(二维dp)
    HDU 4542 小明系列故事——未知剩余系 (数论|反素数)
    51nod 1060 最复杂的数(反素数)
    eclipse hadoop环境搭建 查看HDFS文件内容
    Windows jdk安装以及版本切换
    WIN10配置MongoDB
    Oracle 11g R2 for Win10(64位)的安装步骤
  • 原文地址:https://www.cnblogs.com/joyzhuang/p/3953762.html
Copyright © 2011-2022 走看看