为什么选择GO
- 高性能、高并发
- 语法简单、学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译,拥有最快的编译速度,一万个微服务编译一分钟
- 跨平台
- 垃圾回收
为什么ByteDance选择GO
- 最初选择
python,2014年开始,由于性能问题换成了GO - C++不适合在线web业务
- 早期团队非JAVA背景
- 性能好
- 部署容易,上手简单
- 内部RPC和HTTP推广
go 基础语法
GO是强类型语言,如 int,string,float,bool
声明方式:
var a = "initial"
var b,c int =1,2
f:=float32(e)
if语句
//if语句
if 7%2==0{
fmt.Println("这个是if语句,用于判断7%2是否为0")
}
while循环体(用一个for循环替代)
for{
fmt.Println("loop")
}
for循环体
//循环
for n:=0;n<5;n++{
if n%2==0{
continue
}
fmt.Println(n)
}
switch语句
//switch
switch a{
case 1:
}
//默认只运行一个分支case
! 值得注意的是,GO里面只有一个默认的case会被执行,即不像其他语言一样要写default和break,go是执行完了这个case之后就跳出switch语句了
数组
//数组
var a[5] int
//切片
s:=make([]string,3)//make创建切片
s=s.append(s,"d")//必须把结果赋值给原切片
fmt.Println(s)//[d]
c:=make([]string,len(s))
copy(c,s)
map
//map
m:=make(map[string]int)//第一个是key类型,第二个是value的类型
m["one"]=1
m["two"]=2
fmt.Println(m)//map[one:1 two:2]
fmt.Println(len(m))//2
//map既可以单个单个访问,也可以遍历访问
//读取map
r,ok:=m["unknow"]//ok是这个键的值
range体,用于遍历内置容器
//range
for i,num:=range nums{
}
指针
//指针主要用于对参数修改
package main
import "fmt"
func add2(n int) {
n += 2//在函数中修改了n,但是不会影响到函数之外的n,也就是说,函数执行完之后,n是多少还是多少
}
func add2ptr(n *int) {
*n += 2//指针会修改变量本身的值
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7
}
结构体
package main
import "fmt"
type user struct {
name string
password string
}
func main() {
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d) // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
fmt.Println(checkPassword(a, "haha")) // false
fmt.Println(checkPassword2(&a, "haha")) // false
}
func checkPassword(u user, password string) bool {
return u.password == password
}
func checkPassword2(u *user, password string) bool {
return u.password == password
}
结构体方法
package main
import "fmt"
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
error
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // wang
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // not found
return
} else {
fmt.Println(u.name)
}
}
这个应该是go的一大亮点了,不需要用到try-catch语句块去处理错误
json
json格式应该是用的最多的了,所以这个重点要记一下
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string
Age int `json:"age"`
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // [123 34 78 97...]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}
go 并发
协程的概念:协程是用户态的,轻量级的线程,栈KB级别 线程的概念:内核态,线程跑多个协程,栈MB级别 这也是GO天生适合高并发的原因
示例代码:
func hello(i int) {
println("Hello goroutine: " + fmt.Sprint(i))
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
go提倡通过通信共享内存,也就是通过channel 而不是通过共享内存通信
channel 具体操作:
make(chan 元素类型,[缓冲大小])
- 无缓冲通道
make(chan int) - 有缓冲通道
make(chan int,2)
go的线程主要用于做高并发的使用
go应该是可以作为我替代java的一个选择了,不仅仅是go的语法简单,而且开发效率高,有着python一样的开发速度,同时又有着C++一样的性能,可以作为替代java和python开发后端的一大利器。