【注意】最后更新于 June 12, 2020,文中内容可能已过时,请谨慎使用。
想换个语言开发的同学可以看这里
概况
go 相比 php 有哪些优势?
- go 的部署简单, 运行时只要把一个二进制文件扔到机器上就行, 这一点在容器化方面优势很大
- 可控的多线程和更简单的多线程间通信
- 编译型语言对动态语言天生的性能优势, 变量在开发过程中不会突然从 str 变成 array
- 微服务相关的项目多
- 自 go 1.5 以后, 底层完全采用的 go 自己的代码重构
go 本身的优势
- 开发效率和运行的效率都在可接受范围
- 成熟的官方库和活跃的社区, 还有官方出品的工具链, 站在巨人的肩膀上
- 语法简单(25个关键字), 对于初学者来说不用受配置环境的苦
- 良好兼容 c 语言
- 语言层面支持并发
- 运行时对外部的依赖极少
go 较于 php 的劣势
- 编译造成的繁琐操作, 本地调试的时候比较烦
- 代码量偏多
- 至今没有一个成熟的依赖库管理工具, 缺乏版本管理(1.15版本之后好一些, 可以体验一下 go mod)
- 字典类型要考虑并发读写安全的问题, 需要有
锁
的概念, 这一点 swoole 也有类似的情况
go 的特色
defer 延迟处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func OpenFile() bool{
file.Open("file/path")
if condition1 {
file.Close()
return false
}
if condition2 {
file.Close()
return false
}
file.Close()
return true
}
|
对比一下
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func OpenFile() bool{
file.Open("file/path")
defer file.Close()
if condition1 {
return false
}
if condition2 {
return false
}
return true
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
...
func main () {
for i :=0;i < 5 ; i++{
defer fmt.Println("输出:",i)
}
}
...
// 输出: 4
// 输出: 3
// 输出: 2
// 输出: 1
// 输出: 0
|
多返回值
1
2
3
4
5
6
7
|
func multipartReturn(a int, b int) (res int, err error) {
res = a + b
if res > 3 {
return res, nil
}
return 0, errors.New("math: square root of negative number")
}
|
goroutinue 并发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func main() {
syncChan := make(chan int, 2)
go loop(true, syncChan)
loop(false, syncChan)
<-syncChan
fmt.Println("done")
}
func loop(desc bool, syncChan chan int) {
if desc {
for i := 10; i > 0; i-- {
fmt.Printf("loop1: %d \n", i)
}
// 这个防止子线程提前退出
syncChan <- 1
} else {
for j := 0; j < 10; j++ {
fmt.Printf("loop2: %d \n", j)
}
}
}
|
channel 多线程通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
func main() {
// 创建一个缓冲
ch := make(chan string, 3)
go loopPro(true, ch)
go loopPro(false, ch)
for i := 0; i < 20; i++ {
fmt.Print(<-ch)
}
}
// 加入 channel 的概念
func loopPro(desc bool, ch chan<- string) {
if desc {
for i := 10; i > 0; i-- {
time.Sleep(time.Second)
ch <- fmt.Sprintf("loop1: %d \n", i)
}
} else {
for j := 0; j < 10; j++ {
time.Sleep(time.Second)
ch <- fmt.Sprintf("loop2: %d \n", j)
}
}
}
|
跨平台
http-server
的 demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package main
import (
"fmt"
"net/http"
)
func main() {
fmt.Println("route: http://localhost:9090/")
fmt.Println("route: http://localhost:9090/hello")
mux := http.NewServeMux()
mux.HandleFunc("/hello", helloHandler)
mux.HandleFunc("/", pageHandler)
http.ListenAndServe(":9090", mux)
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world"))
}
func pageHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi baby"))
}
|
可根编译成指定平台的执行文件
1
2
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
|
调用 c 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package main
/* 下面是 C 代码 */
// int add(int a, int b) {
// return a + b;
// }
import "C"
import "fmt"
func main() {
a := C.int(1)
b := C.int(2)
value := C.add(a, b)
fmt.Printf("%v\n", value)
}
|
代码来源
大体了解一下语法
安装
官网安装包地址: https://golang.org/dl/
以 centos 为例
1
2
3
4
|
$ wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
$ tar -C /usr/local -zxvf go1.11.linux-amd64.tar.gz
$ export PATH=$PATH:/usr/local/go/bin/
$ go
|
GOROOT 不用管它…
GOPATH 目录结构
1
2
3
|
bin/ # 生成的执行文件
pkg/ # 编译时用到的外部库执行文件
src/ # 我们开发的各种库和 go get 到的各种库源码
|
Hello world
1
2
3
4
5
6
7
8
9
|
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
|
运行 go run main.go
资源类型
常用:
int/int8/int16/int32/int64
uint/uint8/uint16/uint32/uint64
float32/float64
string
array
slice
(切片)
map
(字典)
point
(指针)
面向对象:
特色:
变量赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var a int
a = 1
// 或
a := 1
// 数组
var arr [10]int
// 切片
var slice1 []int = make([]int, 3)
var slice1 := make([]int, 3, 10) // 预留了10字节内存
slice1 = []int{1, 2, 3}
slice2 := slice1[2:] // [3]
var any interface{} // 空接口接一切
any = slice2 // [3]
// 字典
var mp map[string]string
mp["a"] = "诶"
mp["b"] = "必"
// 同上
mp := map[string]string{"a": "aaa", "b": "bbb"}
// 这样写得清楚这是干什么的
var mp map[string]interface{}
|
逻辑处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
for i := 0;i < 5 ; i++ {
fmt.Println("输出:",i)
}
if i > 1 {
....
}
// 隐式执行 break
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
fmt.Printf("%s.", os)
}
|
面向对象
struct
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package main
import (
"fmt"
)
type human struct {
Name string
Age int
}
// 隐式的继承 human 的属性
type ming struct {
human
Skill string
}
// 添加结构体所属的方法
func (h human) Say() {
fmt.Printf("我叫%s,今年%d", h.Name, h.Age)
}
func main() {
var xm ming
xm.Name = "小明"
xm.Age = 18
xm.Skill = "跑得快"
fmt.Println(xm)
xm.Say()
}
|
interface
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。 – 鸭子类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package main
import (
"fmt"
)
type Animal interface {
Speak() string
}
type Dog struct {
}
func (d Dog) Speak() string {
return "Woof!"
}
type Cat struct {
}
func (c Cat) Speak() string {
return "Meow!"
}
type PHPProgrammer struct {
}
func (p PHPProgrammer) Speak() string {
return "PHP is the best language! "
}
type PassBy struct {
}
func main() {
animals := []Animal{Dog{}, Cat{}, PHPProgrammer{}}
// animals[3] = PassBy{} // 编译不会通过, 因为没有实现 Animal 接口
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}
|
demo 代码地址
基于go的应用和开源工具
等等…
文章作者
GPF
上次更新
2020-06-12
(f96a3ef)