Go快速上手
Go快速上手Go介绍基本介绍Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。优势可直接编译成机器码不依赖其他库直接运行即可部署语言层面的并发,能充分利用多核GO项目1、云计
Go快速上手
Go介绍
基本介绍
Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。
优势
- 可直接编译成机器码
- 不依赖其他库
- 直接运行即可部署
- 语言层面的并发,能充分利用多核
GO项目
1、云计算基础设施领域
代表项目: docker、kubernetes、 etcd、 consul、 cloudflare CDN、七牛云存储等。
2、基础后端软件
代表项目: tidb、 influxdb、 cockroachdb等 。
3、微服务
代表项目: go-kit、micro、 monzo bank的typhon、bilbili等 。
4、互联网基础设施
代表项目:以太坊、hyperledger等 。
Go不足
-
包管理,大部分包在github上
-
所有Excepiton都用Error来处理(比较有争议)。
-
对C的降级处理,并非无缝,没有C降级到asm那么完美(序列化问题)
环境安装
-
基本环境
-
win10家庭版
-
IntelliJ IDEA 2021.3.2(GOLAND等也行)
-
-
go的环境
参考其中的 “环境准备” 章节即可
(3条消息) 以太坊源码阅读1——准备环境_mo_seele的博客-CSDN博客
HelloWorld
创建项目
- 选择go类型
- 之后取个名下一步即可
代码
创建main包,在该包下创建 main.go文件
package main
import "fmt"
func main() {
fmt.Println("hello World")
}
变量与常量
变量声明
- 声明
var a int
- 声明+赋值
var b int = 100
- 省略类型的自动匹配
var c= 100
- 直接自动匹配(最常用,但只能在函数体内用)
e := 100
- 声明多个变量
var xx,yy int = 100, 200
- 多行地声明多个变量
var(
vv int = 100
jj bool = true
)
常量声明
- 常量(只读属性)
const length int = 10
- const定义枚举
const(
ONE = 1
TWO = 2
)
- iota+const
注:可以在const()添加一个关键字iota,每行的iota都会累加1, 第1行的iota的默认值是0
变量内部结构
函数
基本函数
- 单返回值函数
func fun(a int, b int) int {
return a + b
}
- 多返回值函数
func fun1(a int, b int) (int, int, int) {
return a, b, a + b
}
- 带形参的多返回
func fun2(x int, y int) (a int, b int, c int) {
c = x + y
return
}
- 形参简写的多返回
func fun3(x int, y int) (a, b, c int) {
c = x + y
return
}
函数调用顺序
导包
- import _ “fmt” :给fmt起一个别名,匿名,无法使用当前包的方法,但会执行当前的包的内部的init()方法
- import aa “fmt” ; 给fmt包起一个别名,aa。Println()来调用
- import . “fmt” 将当前fmt包中的全部方法,导入到当前本包中,可以直接调用
指针
数组
声明
- 固定长度数组
var arr1 [10] int
myArray2 := [10] int{1,2,3,4}
- 动态数组(切片)
myarr := []int{1,2,3,4}
- 动态数组(切片),使用make
var slice[]int = make([]int,3)
遍历
- 基本遍历(for)
for i := 0; i < len(myArray2); i++ {
fmt.Println(myArray2[i])
}
- 增强for
myArray2 := [10]int{1, 2, 3, 4}
for i, v := range myArray2 {
fmt.Println(i, "", v)
}
- 匿名遍历
myArray2 := [10]int{1, 2, 3, 4}
for _, v := range myArray2 {
fmt.Println( v)
}
切片操作
- 切片追加
myArray2 := make([]int, 3, 5) //3是长度(length),5是容量(cap)
myArray2 = append(myArray2, 1)
myArray2 = append(myArray2, 2)
myArray2 = append(myArray2, 3)
fmt.Println(myArray2)
当append 3 时,由于当前切片的容量不足,会自动追加大小为初始容量的空间
所以append 3 时,容量为10
其他
- 查看数组类型
fnt.Printf("myArray3 types = T\n",myArray3)
-
动态数组在传参上是引用传递,而且不同元素长度的动态数组他们的形参是一致。|
-
判断一个slice为空
if slice == nil{
。。。
}
其他
defer
会在函数返回后执行,当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出),下面的代码是将一系列的数值打印语句按顺序延迟处理,如下所示:
package main
import (
"fmt"
)
func main() {
fmt.Println("defer begin")
// 将defer放入延迟调用栈
defer fmt.Println(1)
defer fmt.Println(2)
// 最后一个放入, 位于栈顶, 最先调用
defer fmt.Println(3)
fmt.Println("defer end")
}
defer begin
defer end
3
2
1
map
创建
- 声明创建
var myMap map[string]string = make(map[string]string, 10)
myMap["1"] = "one"
myMap["2"] = "two"
- 省略创建
myMap2 := make(map[string]string)
myMap2["1"] = "one"
myMap2["2"] = "two"
- 初始化创建
myMap3 := map[string]string{
"1": "one",
"2": "two",
"3": "three",
}
操作
- 增加
myMap2["1"] = "one"
- 修改
myMap2["1"] = "three"
- 遍历
for key, val := range myMap2 {
fmt.Println(key)
fmt.Println(val)
}
- 删除
delete(myMap2, "2")
- map作为形参时,传递的是指针,是引用传递
对象
- 基本使用
type Book struct {
title string
auth string
}
func main() {
var book Book
book.title = "11"
book.auth = "22"
fmt.Println(book)
}
-
结构体在传参时默认是传值,如果要传地址要用指针
-
方法(与函数不同,可以理解为是绑定到结构体上的函数)
func (this Book) getTit() {
fmt.Println(this.Title)
}
func main() {
book := Book{Title: "11", Auth: "22"}
book.getTit()
}
-
当首字母大写时,表示在其他包也能使用,小写则只能在本包使用
-
继承 (方法也会继承)
type Paper struct {
Content string
}
type Book struct {
Paper
Title string
Auth string
}
- 定义子类对象
接口
- 多态
type Anima interface {
Sleep()
getName() string
}
type Cat struct {
color string
}
func (Cat Cat) Sleep() {
fmt.Println("")
}
func (Cat Cat) getName() string {
return Cat.color
}
func main() {
var ani Anima = &Cat{color: "66"}
fmt.Println(ani.getName())
}
- 断言与万能数据类型
func Sleep(arg interface{}) interface{} {
//类型断言
value, ok := arg.(string)
if ok {
fmt.Println("ok")
}
return value
}
func main() {
fmt.Println(Sleep("123"))
}
输出
ok
123
反射
- 基本使用
type User struct {
name string
pwd string
}
func ReflectTry(inter interface{}) {
//获取类型
interType := reflect.TypeOf(inter)
fmt.Printf(interType.Name() + "\n")
//获取value
interVal := reflect.ValueOf(inter)
fmt.Println(interVal)
//获取属性
field := interType.Field(0)
fieldVal := interVal.Field(0)
fmt.Println(field.Name, field.Type, fieldVal)
}
func main() {
user := User{name: "123", pwd: "456"}
ReflectTry(user)
}
输出
User
{123 456}
name string 123
- 获取方法
type User struct {
name string `info:"remark" doc:"我的名字"`
pwd string `info:"password" `
}
func (this *User) UserTry() {
fmt.Print(this)
}
func ReflectTry(inter interface{}) {
//获取方法
interType := reflect.TypeOf(inter)
println(interType.NumMethod())
println(interType.Method(0).Name)
}
func main() {
user := User{name: "123", pwd: "456"}
ReflectTry(&user)
}
输出
1
UserTry
- Tag标签
type User struct {
name string `info:"remark" doc:"我的名字"`
pwd string `info:"password" `
}
func main() {
user := User{name: "123", pwd: "456"}
ReflectTry(&user)
}
func ReflectTry(inter interface{}) {
//获取类型
interElem := reflect.TypeOf(inter).Elem()
println(interElem.NumField())
tagInfo := interElem.Field(0).Tag.Get("info")
fmt.Println(tagInfo)
}
输出
2
remark
- 使用tag进行json化
type User struct {
Name string `json:"title" `
Pwd string `json:"password" `
}
func main() {
user := User{"名字", "密码"}
str, err := json.Marshal(user)
if err != nil {
return
}
fmt.Printf("%s", str)
}
结果
{"title":"名字","password":"密码"}
goroutine 多线程
基本
缺点:
- 创建、销毁、调度G都需要每个M获取锁,这就形成了激烈的锁竞争。
- M转移G会造成延迟和额外的系统负载。
- 系统调用(CPU在M之间的切换)导致频繁的线程阻塞和取消阻塞操作增加了系统开销。
后期修改:
- 多线程代码
func mulTask() {
for i := 0; i < 10; i++ {
fmt.Printf("side---%d\n", i)
time.Sleep(1 * time.Second)
}
}
func main() {
go mulTask()
for i := 0; i < 10; i++ {
fmt.Printf("main---%d\n", i)
time.Sleep(1 * time.Second)
}
}
输出
main---0
side---0
side---1
main---1
main---2
side---2
......
channel 通信
func mulTask() {
c <- 666
}
func main() {
c = make(chan int)
go mulTask()
num := <-c
println(num)
}
select
Go Modules
介绍
Go modules是Go语言的依赖解决方案,发布于Go1.11,成长于Go1.12,丰富于Go1.13,正式于Go1.14推荐在生产上使用。Go moudles目前集成在Go的工具链中,只要安装了Go,自然而然也就可以使用Go moudles了,而Go modules的出现也解决了在Go1.11前的几个常见争议问题:
- Go语言长久以来的依赖管理问题。
- “淘汰"现有的GOPATH的使用模式。
- 统一社区中的其它的依赖管理工具(提供迁移功能)。
Go Path问题
-
无版本控制概念
-
无法同步一致第三方版本号
-
无法指定当前项目引用的第三方版本号
Go mod使用
- 命令
go mod环境变量
可以通过go env命令来进行查看
G0111MODULE
Go语言提供了G0111MODULE这个环境变量来作为Go modules的开关,其允许设置以下参数:
- auto: 只要项目包含了go.mod文件的话启用Go modules, 目前在Go1.11至Go1.14中仍然是默认值。
- or:启用Go modules, 推荐设置,将会是未来版本中的默认值。
- off: 禁用Go modules, 不推荐设置。
GoProxy
这个环境变量主要是用于设置Go模块代理(Go module proxy) ,其作用是用于使Go在后续拉取模块版本时直接通过镜像站点来快速拉取。
GOPROXY的默认值是: https://proxy.golang.org direct proxy. golang. org国内访问不了,需要设置国内的代理.
- 阿里云
https:/ / mirors.aliyun.com/ goproxy/ - 七牛云
https:/ / goproxy.cn,direct
其他
参考
更多推荐
所有评论(0)