为何是Go语言
- 类C的语法,这意味着Java、C#、JavaScript程序员能很快的上手
- 有本身的垃圾回收机制
- 跨平台、编译便可执行无需安装依赖环境
- 支持反射
Go语言简介
Go 语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go 是很是年轻的一门语言,它的主要目标是“兼具Python等动态语言的开发速度和 C/C++ 等编译型语言的性能与安全性”。html
数据类型
数据类型 | 说明 |
---|---|
bool | 布尔 |
string | 字符串 |
int | uint8,uint16,uint32,uint64,int8,int16,int32,int64 |
float | float32,float64 |
byte | byte |
基本语法
HelloWorld
package main import "fmt" var name string func init() { name = "world" } func main() { fmt.Println("hello " + name) } 复制代码
咱们来执行一下:shell
$ go run main.go # main.go 为刚刚建立的那个文件的名称 $ hello world 复制代码
变量
变量声明
package main import ( "fmt" ) func main() { var name string // 声明 name = "da'mao'mao" // 赋值 fmt.Println(name) var age int = 18 // 声明并赋值 fmt.Println(age) } 复制代码
类型推断
package main import ( "fmt" ) func main() { name := "damaomao" fmt.Println(name) age := 18 fmt.Println(age) } 复制代码
函数
try cachethrowerror
下面咱们经过一个示例来了解一下,在线运行示例:play.golang.org/p/PYy3ueuPF…bash
package main import ( "errors" "fmt" "strconv" ) func main() { log1() log2("hello world") ret1 := add1(1, 1) fmt.Println("add1 result:" + strconv.Itoa(ret1)) ret2, err := Add2(0, 1) if err == nil { fmt.Println("Add2 result:" + strconv.Itoa(ret2)) } else { fmt.Println("Add2 error", err) } } // 私有、无入参、无返回值 func log1() { fmt.Println("execute func log1") } // 私有、入参、无返回值 func log2(msg string) { fmt.Println("execute func log2:" + msg) } // 私有、两个入参、一个返回值 func add1(count1, count2 int) int { total := count1 + count2 fmt.Println("execute func add3, result=" + strconv.Itoa(total)) return total } // Public、两个入参、多个返回值 func Add2(count1, count2 int) (int, error) { if count1 < 1 || count2 < 1 { return 0, errors.New("数量不能小于1") } total := count1 + count2 return total, nil } 复制代码
该示例输出结果为:架构
execute func log1 execute func log2:hello world execute func add3, result=2 add1 result:2 Add2 error 数量不能小于1 复制代码
_
_, err := Add2(1, 2) if err != nil { fmt.Println(err) } 复制代码
空白符特殊在于实际上返回值并无赋值,因此你能够随意将不一样类型的值赋值给他,而不会因为类型不一样而报错。异步
结构体
classstructclass
type User struct { Name string Gender string Age int } 复制代码
User
user := User{ Name: "hahaha", Gender: "男", Age: 18, // 值得一提的是,最后的逗号是必须的,不然编译器会报错,这就是go的设计哲学之一,要求强一致性。 } 复制代码
结构体的属性能够在结构体内直接声明,那么如何为结构体声明函数(即Java中的方法)呢,咱们来看下下面的示例:在线运行示例:play.golang.org/p/01_cTu0Rz…
package main import "fmt" type User struct { Name string Gender string Age int } // 定义User的成员方法 func (u *User) addAge() { u.Age = u.Age + 1 } func main() { user := User{ Name: "哈", // 名称 Gender: "男", // 性别 Age: 18, // 值得一提的是,最后的逗号是必须的,不然编译器会报错,这就是go的设计哲学之一,要求强一致性。 } user.addAge() fmt.Println(user.Age) } 复制代码
指针类型和值类型
Java中值类型和引用类型都是定死的,int、double、float、long、byte、short、char、boolean为值类型,其余的都是引用类型,而Go语言中却不是这样。
在Go语言中:
&a&aa*b := &ab&a*b
下面咱们来看下例子,在线运行:play.golang.org/p/jxAKyVMjn…
package main import ( "fmt" ) func main() { a := "123" b := &a fmt.Println(a) fmt.Println(b) fmt.Println(*b) } 输出结果为: 123 0x40c128 123 复制代码
并发编程
Go语言的并发是基于 goroutine 的,goroutine 相似于线程,但并不是线程。能够将 goroutine 理解为一种虚拟线程。Go语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每一个 CPU 中,最大限度地使用CPU性能。
Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数建立一个默认的 goroutine。
下面咱们来看一个例子(在线演示:play.golang.org/p/U9U-qjuY0…
package main import ( "fmt" "time" ) func main() { // 建立一个goroutine go runing() // 建立一个匿名的goroutine go func() { fmt.Println("喜特:" + time.Now().String()) }() // 这里sleep一下是由于main方法若是执行完了,main该程序建立的全部goroutine都会退出 time.Sleep(5 * time.Second) } func runing() { fmt.Println("法克:" + time.Now().String()) time.Sleep(3 * time.Second) } 输出: 法克:2009-11-10 23:00:00 +0000 UTC m=+0.000000001 喜特:2009-11-10 23:00:00 +0000 UTC m=+0.000000001 复制代码
喜特
若是说 goroutine 是Go语言程序的并发体的话,那么 channel 就是它们之间的通讯机制。一个 channel 是一个通讯机制,它可让一个 goroutine 经过它给另外一个 goroutine 发送值信息。每一个 channel 都有一个特殊的类型,也就是 channel 可发送数据的类型。一个能够发送 int 类型数据的 channel 通常写为 chan int。
下面咱们利用goroutine+channel来实现一个生产消费者模型,示例代码以下:(在线执行:play.golang.org/p/lqUBugLdU…
package main import ( "fmt" "time" ) func main() { // 建立一个通道 channel := make(chan int64) // 异步去生产 go producer(channel) // 数据消费 consumer(channel) } // 生产者 func producer(channel chan<- int64) { for { // 将数据写入通道 channel <- time.Now().Unix() // 睡1秒钟 time.Sleep(time.Second) } } // 消费者 func consumer(channel <-chan int64) { for { timestamp := <-channel fmt.Println(timestamp) } } 输出为以下:(每秒钟打印一次) 1257894000 1257894001 1257894002 1257894003 复制代码
Java程序员以为很差用的地方
tag
参考
做者简介
大猫猫,互联网公司老码农、不折腾不舒服斯基,多年千万日活服务端研发和架构经验。
- 码农俱乐部:mlog.club