文档章节

《Google Go: A Primer》学习笔记

 学习吧
发布于 2015/10/12 20:35
字数 1734
阅读 85
收藏 5
点赞 0
评论 0

#What is Go? simple,fast,safe and concurrent #Reading Go 编辑hello.go

package main
import "fmt"
func main(){
    fmt.Println("Hello World!你好,世界!")
}
经典的Hello World

运行hello.go: 方式1、

go run hello.go
超快的编译速度,使得go可以像php一样执行

方式2、

go build hello.go
./hello

编译执行,go可以像C、C++一样发布

#Variable Declarations

var sum int
var total int=42
var a,b *int
var label="name"
name:="Samuel"
像Python一样方便的变量初始化

#Conditionals

result:=someFunc()
if result>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
fmt.Println(result)
if result:=someFunc();result>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
if someFunc()>0{
    fmt.Println("result>0")
}else{
    fmt.Println("result<=0")
}
if a>0{
    fmt.Println("positive")
}else if a<0{
    fmt.Println("negative")
}else{
    fmt.Println("zero")
}

#Switches

byte:='b'
var result int
switch byte{
case 'a','b':
    result=1
default:
    result=0
}
fmt.Println(result)
switch result:=calculate();true{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
switch result:=calculate();{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
switch calculate();{
case result<0:
    fmt.Println("negative")
case result>0:
    fmt.Println("positive")
default:
    fmt.Println("zero")
}
方便的switch

#Loops ##Condition

a:=10
b:=0
for a>b{
    fmt.Println(a,b)
    a--
    b++
}

##Initializer,Condition and Step

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

##Range

for i:=range "hello"{
    fmt.Println(i)
}

输出0到4

for i,ch:=range "hello"{
    fmt.Printf("%d,%c\n",i,ch)
}

##Infinite

i:=0
for{
    if i>=10{
        break
    }
    fmt.Println(i)
    i++
}
所有编程语言中最简单的循环

#Funtions

func add(a,b int)int{
    return a+b
}
fmt.Println(add(1,2))
支持C风格的函数定义
add:=func(a,b int)int{
    return a+b
}
fmt.Println(add(1,2))
支持匿名函数定义

##Multiple Return Values

func divide(a,b int)(int,int){
    quotient:=a/b
    remainder:=a%b
    return quotient,remainder
}
func divide(a,b int)(quotient,remainder int){
    quotient=a/b
    remainder=a%b
    return quotient,remainder
}
fmt.Println(divide(7,2))
quotient,_:=divide(18,4)
支持返回值名称
func moreMagic()(int,bool){
    return 7,true
}
if result,ok:=moreMagic();ok{
    fmt.Println(result)
}
go多返回值使错误处理变得简单、高效

##Anonymous Functions

func makeAdder(x int)(func(int)int){
    return func(y int)int{return x+y}
}
add5:=makeAdder(5)
add36:=makeAdder(36)
fmt.Println("The answer:",add5(add36(1)))
支持闭包,才是真正地支持匿名函数。
package main
import "fmt"
func main(){
    for i:=0;i<10;i++{
        defer fmt.Println("Hello",i)
        fmt.Println("World")
    }
}

输出10个World、10个Hello

函数结束执行defer
package main
import "fmt"
func main(){
    for i:=0;i<10;i++{
        func(){
            defer fmt.Println("Hello",i)
            fmt.Println("World")
        }()
    }
}

输出10个World、Hello

defer和匿名函数可以完全实现RAII、完全实现try finally。读者可以举出RAII/try finally的例子,我采用defer和匿名函数实现。

#Primitive Types ##Arrays & Slices

a:=[...]int{1,2,3,4,5,6,7,8,9,0}
fmt.Println(a)
fmt.Println(len(a))
s:=a[3:5]
fmt.Println(s)
fmt.Println(len(s))
fmt.Println(cap(s))
s=a[3:]
fmt.Println(s)
fmt.Println(len(s))
fmt.Println(cap(s))
类似Python的数组切片
s[0]=42
fmt.Println(a[3])
s=s[1:]
fmt.Println(s)
s1:=[]int{1,2,3,4,5};
fmt.Println(s1)
s2:=make([]int,10)
fmt.Println(s2)

##Maps

内置字典非常重要。C++ STL中map采用库实现,比自己手工实现的红黑树速度慢;多线程并发需要互斥锁锁死,导致速度更慢。go的Maps线程安全,并有可能实现高效。
m:=make(map[string]int)
m["foo"]=42
m["bar"]=30
fmt.Println(m["foo"])
写字典
x,ok:=m["bar"]
fmt.Println(x,ok)
读字典
_,ok=m["baz"]
fmt.Println(ok)
m["foo"]=0
_,ok=m["foo"]
fmt.Println(ok)
delete(m,"bar")
x,ok=m["bar"]
fmt.Println(x,ok)
删除字典数据,可以看作一种读字典

#Object Orientation ##Structs

type Point struct{
    x,y float64
}
var p *Point=new(Point)
fmt.Println(p)
var p1 Point=Point{3,4}
fmt.Println(p1)
var p2 *Point=&Point{3,4}
fmt.Println(p2)
p3:=Point{3,4}
fmt.Println(p3)
p4:=&Point{3,4}
fmt.Println(p4)
p5:=&Point{x:3,y:4}
fmt.Println(p5)

##Methods

func (self *Point) SetX(x float64) {
    self.x = x
}

修改对象需要引用语义。

func (self Point) Length() float64 {
    return math.Sqrt(self.x*self.x + self.y*self.y)
}
获取对象数据只需要值语义。
p := &Point{3, 4}
fmt.Println(p, p.Length())
p.SetX(5)
fmt.Println(p, p.Length())

##Interfaces 面向接口很重要

依赖倒置原则:
高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
package main
import (
    "bufio"
    "fmt"
    "os"
)
type Widget struct{}
func (Widget)Frob(){
    fmt.Println("Widget.Frob")
}
type Sprocket struct{}
func (Sprocket)Frob(){
    fmt.Println("Sprocket.Frob")
}
type Frobber interface{
    Frob()
}
func frobtastic(f Frobber){
    f.Frob()
}
func main(){
    var f Frobber
    reader:=bufio.NewReader(os.Stdin)
    b,_,_:=reader.ReadLine()
    line:=string(b)
    if line=="Widget"{
        f=&Widget{}
    }else if line=="Sprocket"{
        f=&Sprocket{}
    }else{
        return
    }
    frobtastic(f)
}

It is important to note that every object implements the empty interface: interface {}

go实现了非嵌入式接口,即实现了模板编程,又统一了面向对象编程和模板编程。

##Inheritance

type Base struct {
    i int
}
func (b Base) Magic() {
    fmt.Println("base magic", b.i)
}
func (self Base) MoreMagic() {
    self.Magic()
    self.Magic()
}
type Foo struct {
    Base
}
func (f Foo) Magic() {
    fmt.Println("foo magic", f.i)
}
f := &Foo{Base{1}}
f.Magic()
f.MoreMagic()
注意go没有虚函数。

#Concurrency Do not communicate by sharing memory; instead, share memory by communicating. 不要通过共享内存来通信,而应该通过通信来共享内存。 ##Goroutines

package main
import ("fmt";"time")
func DoThis(){
    for i:=0;i<10;i++{
        fmt.Println("DoThis",i)
        time.Sleep(1e3)
    }
}
func main(){
    go func(){
        for i:=0;i<10;i++{
            fmt.Println("func",i)
            time.Sleep(1e3)
        }
    }()
    go DoThis()
    time.Sleep(1e9)
}

##Channels

package main
import ("fmt";"runtime")
func DoThis(ch chan int){
    result:=0
    for i:=0;i<1000000;i++{
        result+=i
    }
    ch<-result
}
func main(){
    runtime.GOMAXPROCS(runtime.NumCPU())
    ch:=make(chan int,5)
    go func(){
        result:=0
        for i:=0;i<1000000;i++{
            result+=i
        }
        ch<-result
    }()
    go DoThis(ch)
    fmt.Println(<-ch)
    val,ok:=<-ch
    fmt.Println(val,ok)
}
chan是生产者消费者的一个实现。
runtime.GOMAXPROCS支持动态设置,go多核并行。
ch := make(chan int)
go func() {
    time.Sleep(time.Second * 5)
    ch <- 0
}()
select {
case <-time.After(time.Second * 2):
    fmt.Println("timeout")
case i := <-ch:
    fmt.Println(i)
}
chan可以实现超时

单向channel:

ch4:=make(chan int)
ch5:=<-chan int(ch4)		//单向读取
ch6:=chan<- int(ch4)		//单向写入
C/C++中const实现语法级确定数据流向是个坑,单向channel很好地解决了这个问题。

关闭channel:

close(ch)
func fibonacci(n int, c chan int) {
    x, y := 1, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
    fmt.Println(i)
}
面向数据流编程比面向对象编程可以更清晰地解决后台问题。

让出时间片:

func say(s string) {
    for i := 0; i < 5; i++ {
        runtime.Gosched()
        fmt.Println(s)
    }
}
runtime.GOMAXPROCS(1)
go say("World")
say("Hello")

同步锁:sync.Mutex、sync.RWMutex 全局唯一性操作:

var once sync.Once		//全局
once.Do(setup)
C、C++、Java、C#、go等语言都提供了单例模式的实现。

#Packages

src
	main
		hello.go
	Point
		Point.go
export GOPATH=src父目录的全路径

编辑Point.go

Package Point
import "math"
type Point struct{
    x,y float64
}
func NewPoint(x,y float64)*Point{
    return &Point{x,y}
}
func (self Point)Length()float64{
    return math.Sqrt(self.x*self.y+self.y*self.y)
}
func (self *Point)Scale(factor float64){
    self.setX(self.x*factor)
    self.setY(self.y*factor)
}
func (self *Point)setX(x float64){
    self.x=x
}
func (self *Point)setY(y float64){
    self.y=y
}

编辑hello.go

package main
import ("fmt";"Point")
func main(){
    p:=Point.NewPoint(3,4)
    fmt.Println(p.Length())
    p.Scale(10.0)
    fmt.Println(p.Length())
}

运行: 方式一、

go run hello.go

方式二、

go build hello.go
./hello

#What's Missing #总结

  • go支持过程化编程、面向对象编程、函数式编程
  • go支持面向接口编程、模板编程、面向数据流编程
  • go语法比C更明确,比Python更简单
  • go内存自动回收、defer资源回收、支持RAII、支持try finally
  • go简化了错误处理
  • go内置了数组、数组切片、字典
  • go提供了协程、生产者消费者、互斥锁、读写锁、高效多核并行
  • go内置了工程管理工具 Less is more的思想正如《道德经》:
大音希声,大象无形。

© 著作权归作者所有

共有 人打赏支持
粉丝 1
博文 20
码字总数 6841
作品 0
海淀
程序员
迷渡:免费的编程中文书籍索引

本文之前发布过,近半年后,本文作者(迷渡,JustJavaC)大幅度进行了更新,因此再次分享给大家。感谢 @justjavac 和众多的分享者!感谢写作这些文档、手册的人们! 语言无关类 操作系统 开源...

山哥 ⋅ 2015/01/22 ⋅ 4

编程类开放书籍荟萃(转载)

关于开源图书有人在网络上做了大量整理,本文为大家刊载《免费的编程中文书籍索引》 国外程序员在 stackoverflow 推荐的程序员必读书籍,中文版。 stackoverflow 上的程序员应该阅读的非编程...

行者PHPer ⋅ 2016/10/09 ⋅ 0

开源电子书

目录 语言无关类 操作系统 智能系统 分布式系统 编译原理 函数式概念 计算机图形学 WEB服务器 版本控制 编辑器 NoSQL PostgreSQL MySQL 管理和监控 项目相关 设计模式 Web 大数据 编程艺术 ...

zting科技 ⋅ 2017/12/11 ⋅ 0

免费的编程中文书籍索引【收藏速度】

语言无关类 优质博客 PyTab在线手册中心 ImportNew 廖雪峰的官方网站 程序员博客墙 操作系统 开源世界旅行手册 鸟哥的Linux私房菜 Linux 系统高级编程 The Linux Command Line (中英文版) L...

yonghu86 ⋅ 2015/04/15 ⋅ 0

免费的计算机编程类中文书籍

免费的编程中文书籍索引,欢迎投稿。 国外程序员在 stackoverflow 推荐的程序员必读书籍,中文版。 stackoverflow 上的程序员应该阅读的非编程类书籍有哪些? 中文版 github 上的一个流行的编...

justjavac ⋅ 2014/08/13 ⋅ 10

Fanta/free-programming-books-zh_CN

免费的编程中文书籍索引 免费的编程中文书籍索引,欢迎投稿。 国外程序员在 stackoverflow 推荐的程序员必读书籍,中文版。 stackoverflow 上的程序员应该阅读的非编程类书籍有哪些? 中文版...

Fanta ⋅ 2016/11/14 ⋅ 0

Kotlin 资源大全 - 学 Kotlin 看这一篇教程就够了

目录 介绍 官网及文档 中文社区 教程 & 文章 开源库和框架 Demo 其他 介绍 为什么要做这个? 今天凌晨的 Google I/O 上,Google 正式宣布官方支持 Kotlin. 为了让大家更快了解和上手 Kotlin...

稀土君 ⋅ 2017/05/19 ⋅ 0

C++单元测试框架:gtest

[gtest]: https://code.google.com/p/googletest/ C++单元测试框架:[gtest][gtest] 1) 介绍 [gtest][gtest]是Google的C++测试框架,可以帮助开发者更简单快捷得写好C++单元测试。并且无论你...

加壹 ⋅ 2014/03/31 ⋅ 0

总有你要的编程书单(GitHub )

目录 IDE IntelliJ IDEA 简体中文专题教程 MySQL 21分钟MySQL入门教程 MySQL索引背后的数据结构及算法原理 NoSQL Disque 使用教程 Neo4j .rb 中文資源 Redis 命令参考 Redis 设计与实现 The ...

汇智网 ⋅ 2017/11/22 ⋅ 0

free-programming-books-zh.md

语言无关MySQL NoSQL PostgreSQL Web WEB服务器 其它 函数式概念 分布式系统 在线教育 大数据 操作系统 数据库 智能系统 正则表达式 版本控制 程序员杂谈 管理和监控 编程艺术 编译原理 编辑...

银月光海 ⋅ 2016/05/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

NFS介绍 NFS服务端安装配置 NFS配置选项

NFS介绍 NFS是Network File System的缩写;这个文件系统是基于网路层面,通过网络层面实现数据同步 NFS最早由Sun公司开发,分2,3,4三个版本,2和3由Sun起草开发,4.0开始Netapp公司参与并主导...

lyy549745 ⋅ 32分钟前 ⋅ 0

Spring AOP 源码分析 - 筛选合适的通知器

1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析。本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出合适的通知器(Advisor...

java高级架构牛人 ⋅ 55分钟前 ⋅ 0

HTML-标签手册

标签 描述 <!--...--> 定义注释。 <!DOCTYPE> 定义文档类型。 <a> 定义锚。超链接 <abbr> 定义缩写。 <acronym> 定义只取首字母的缩写。 <address> 定义文档作者或拥有者的联系信息。 <apple......

ZHAO_JH ⋅ 57分钟前 ⋅ 0

SylixOS在t_main中使用硬浮点方法

问题描述 在某些使用场景中,应用程序不使用动态加载的方式执行,而是跟随BSP在 t_main 线程中启动,此时应用代码是跟随 BSP 进行编译的。由于 BSP 默认使用软浮点,所以会导致应用代码中的浮...

zhywxyy ⋅ 今天 ⋅ 0

JsBridge原理分析

看了这个Github代码 https://github.com/lzyzsd/JsBridge,想起N年前比较火的Hybrid方案,想看看现在跨平台调用实现有什么新的实现方式。代码看下来之后发现确实有点独特之处,这里先把核心的...

Kingguary ⋅ 今天 ⋅ 0

Intellij IDEA神器常用技巧五-真正常用快捷键(收藏级)

如果你觉得前面几篇博文太啰嗦,下面是博主多年使用Intellij IDEA真正常用快捷键,建议收藏!!! sout,System.out.println()快捷键 fori,for循环快捷键 psvm,main方法快捷键 Alt+Home,导...

Mkeeper ⋅ 今天 ⋅ 0

Java 静态代码分析工具简要分析与使用

本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBugs,PMD,Jtest),最后从功能、特性等方面对它们进行分析和比较,...

Oo若离oO ⋅ 今天 ⋅ 0

SpringBoot自动配置小记

spring-boot项目的特色就在于它的自动配置,自动配置就是开箱即用的本源。 不过支持一个子项目的自动配置,往往比较复杂,无论是sping自己的项目,还是第三方的,都是如此。刚接触会有点乱乱...

大_于 ⋅ 今天 ⋅ 0

React jsx 中写更优雅、直观的条件运算符

在这篇文字中我学到了很多知识,同时结合工作中的一些经验也在思考一些东西。比如条件运算符 Conditional Operator condition ? expr_if_true : expr_if_false 在jsx中书写条件语句我们经常都...

开源中国最帅没有之一 ⋅ 今天 ⋅ 0

vim编辑模式与命令模式

5.5 进入编辑模式 从编辑模式返回一般模式“Esc” 5.6 vim命令模式 命令 :“nohl”=no high light 无高亮,取消内容中高亮标记 "x":保存退出,和wq的区别是,当进入一个文件未进行编辑时,使...

弓正 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部