I. 基准代码
一份基准代码,多份部署
II. 依赖
显式声明依赖关系
III. 配置
在环境中存储配置
IV. 后端服务
把后端服务当作附加资源
V. 构建,发布,运行
严格分离构建和运行
VI. 进程
以一个或多个无状态进程运行应用
VII. 端口绑定
通过端口绑定提供服务
VIII. 并发
通过进程模型进行扩展
IX. 易处理
快速启动和优雅终止可最大化健壮性
X. 开发环境与线上环境等价
尽可能的保持开发,预发布,线上环境相同
XI. 日志
把日志当作事件流
XII. 管理进程
后台管理任务当作一次性进程运行
其他编程语言的弊端。
Go语言是一个可以编译高效,支持高并发的,面向垃圾回收的全新语言。\
特性:
• 秒级完成大型程序的单节点编译。
• 依赖管理清晰。
• 不支持继承,程序员无需花费精力定义不同类型之间的关系。
• 支持垃圾回收,支持并发执行,支持多线程通讯。
• 对多核计算机支持友好。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LJOCrJhJ-1632742431659)(images/image-20210916201905110.png)]
go安装安装文件
https://golang.google.cn/dl/
下载安装二级制文件
重要环境配置
查看本机环境变量: go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=E:\f.Coding\Golang\bin
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=E:\f.Coding\Golang\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=E:\f.Coding\Golang
set GOPRIVATE=
set GOPROXY=https://goproxy.cn
set GOROOT=D:\Tools\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=D:\Tools\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.17
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\ADMINI~1\AppData\Local\Temp\go-build1871142733=/tmp/go-build -gno-record-gcc-switches
命令 | 含义 |
---|---|
install | compile and install packages and dependencies (编译安装包) |
list | list packages or modules |
mod | module maintenance( 依赖管理) |
run | compile and run Go program |
test | test packages (做测试,单元测试) |
tool | run specified go tool (工具测试) |
version | print Go version |
vet | report likely mistakes in packages( 代码静态,编译器检查不出来的错误(不一定导致程序出错,写法错误)) |
get | add dependencies to current module and install them(下载包到本地) |
go build main.go 编译
go build –o bin/mybinary .
GOOS= linux go build mian.go
fmt 给你格式化,空格
go fmt main.go
import "testing"
func TestIncrease(t *testing.T) {
t.Log("Start testing")
increase(1, 2)
}
代码静态检查,发现可能的 bug 或者可疑的构造
str := “hello world!”
// str类型是字符串,格式化输出的时候应该用s%,这里用的d%
fmt.Printf("%d\n", str)
//
fmt.Println(i != 0 || i != 1)
//
words := []string{"foo", "bar", "baz"}
for _, word := range words {
go func() {
fmt.Println(word).
}()
}
res, err := http.Get("https://www.spreadsheetdb.io/")
defer res.Body.Close()
if err != nil {
log.Fatal(err)
}
package main
import (
"fmt"
)
func main() {
name := "testing"
fmt.Printf("%d\n", name)
fmt.Printf("%s\n", name, name)
}
PS E:\f.Coding\Golang\src\github.com\cncamp\golang\examples\module1\govet> go vet main.go
# command-line-arguments
.\main.go:9:2: Printf format %d has arg name of wrong type string
.\main.go:10:2: Printf call needs 1 arg but has 2 args
下载并安装 Git Command Line
https://git-scm.com/downloads
Github
mkdir –p $GOPATH/src/github.com/cncamp
cd $GOPATH/src/github.com/cncamp
代码下载
git clone https://github.com/cncamp/golang.git
修改代码
上传代码
git add filename
git commit –m 'change logs'
git push
官方 playground
https://play.golang.org/
可直接编写和运行 Go 语言程序
国内可直接访问的 playground
https://goplay.tool
go指南
https://tour.go-zh.org/
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
if v:=x-100; v<0{
return v
}
实例一:基本形式
package main
import (
"fmt"
"math"
)
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}
func main() {
fmt.Println(sqrt(2), sqrt(-4))
}
示例二:简短形式
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
分支很多的情况,if的多条件
switch var1 {
case val1: //空分支
case val2:
fallthrough //执行case3中的f()
case val3:
f()
default: //默认分支
...
示例
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("When's Saturday?")
today := time.Now().Weekday()
switch time.Saturday {
case today + 0:
fmt.Println("Today.")
case today + 1:
fmt.Println("Tomorrow.")
case today + 2:
fmt.Println("In two days.")
default:
fmt.Println("Too far away.")
}
}
特别注意
1,golang中switch每个case中默认自带break,执行完后就退出了,不会执行下面条件。
2,fallthrouth意思是不退出继续执行下面的语句。
go 语言只有一种循环:for循环
for i:=0; i<10;i++{
sum+=i
}
for ; sum < 1000; {
sum += sum
}
for {
if condition1 {
break
}
}
示例
package main
import (
"fmt"
)
func main() {
for i := 0; i < 3; i++ {
fmt.Println(i)
}
fullString := "hello world"
fmt.Println(fullString)
for i, c := range fullString {
fmt.Println(i, string(c))//循环打印下标和字符串
}
}
for index, char := range myString {
...
}
for key, value := range MyMap {
...
}
for index, value := range MyArray {
...
}
需要注意:如果 for range 遍历指针数组,则 value 取出的指
针地址为原指针地址的拷贝
示例
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
变量
var 语句用于声明一个变量列表,跟函数的参数列表一样,类型在最后。
var c, python, java bool
变量的初始化
• 变量声明可以包含初始值,每个变量对应一个。
• 如果初始化值已存在,则可以省略类型;变量会从初始值中获得类型。
var i, j int = 1, 2
短变量声明
• 在函数中,简洁赋值语句 := 可在类型明确的地方代替 var 声明。
• 函数外的每个语句都必须以关键字开始(var, func 等等),因此 := 结构不能在函数外使用。
c, python, java := true, false, "no!"
类型转换
表达式 T(v) 将值 v 转换为类型 T。
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
i := 42
f := float64(i)
u := uint(f)
类型推导
在声明一个变量而不指定其类型时(即使用不带类型的 := 语法或 var = 表达式语法),变量的类型由右值推导得出。
var i int
j := i // j 也是一个 int
**定义:**相同类型且长度固定连续内存片段
以编号访问每个元素
定义方法
var identifier [len]type
示例
yArray := [3]int{1,2,3}
**定义:**切片是对数组一个连续片段的引用
数组定义中不指定长度即为切片
var identifier []type
切片在未初始化之前默认为nil, 长度为0
常用方法
func main() {
myArray := [5]int{1, 2, 3, 4, 5}
mySlice := myArray[1:3]
fmt.Printf("mySlice %+v\n", mySlice)
fullSlice := myArray[:]
remove3rdItem := deleteItem(fullSlice, 2)
fmt.Printf("remove3rdItem %+v\n",
remove3rdItem)
}
func deleteItem(slice []int, index int) []int {
return append(slice[:index], slice[index+1:]...)
}
New 返回指针地址
Make 返回第一个元素,可预设内存空间,避免未来的内存拷贝
示例
package main
import (
"fmt"
)
func main() {
mySlice1 := new([]int)
mySlice2 := make([]int, 0)
mySlice3 := make([]int, 10)
mySlice4 := make([]int, 10, 20)
fmt.Printf("mySlice1 %+v\n", mySlice1)
fmt.Printf("mySlice2 %+v\n", mySlice2)
fmt.Printf("mySlice3 %+v\n", mySlice3)
fmt.Printf("mySlice4 %+v\n", mySlice4)
}
切片是连续内存并且可以动态扩展,由此引发的问题?
a := []int{}
b := []int{1,2,3}
c := a
a = append(b, 1)
修改切片的值?
mySlice := []int{10, 20, 30, 40, 50}
for _, value := range mySlice {
value *= 2
}
fmt.Printf("mySlice %+v\n", mySlice)
for index, _ := range mySlice {
mySlice[index] *= 2
}
fmt.Printf("mySlice %+v\n", mySlice)
声明方法
var map1 map[keytype]valuetype
示例
myMap := make(map[string]string, 10)
myMap["a"] = "b"
myFuncMap := map[string]func() int{
"funcA": func() int { return 1 },
}
fmt.Println(myFuncMap)
f := myFuncMap["funcA"]
fmt.Println(f())
按 Key 取值
value, exists := myMap["a"]
if exists {
println(value)
}
遍历 Map
for k, v := range myMap {
println(k, v)
}
通过 type … struct 关键字自定义结构体
Go 语言支持指针,但不支持指针运算
指针变量的值为内存地址
未赋值的指针为 nil(不存在)
type MyType struct {
Name string
}
func printMyType(t *MyType){
println(t.Name)
}
func main(){
t := MyType{Name: "test"}
printMyType(&t)
}
json:"nodeName,omitempty" protobuf:"bytes,10,opt,name=nodeName"
type MyType struct {
Name string `json:"name"`
}
func main() {
mt := MyType{Name: "test"}
myType := reflect.TypeOf(mt)
name := myType.Field(0)
tag := name.Tag.Get("json")
println(tag)
}
// Service Type string describes ingress methods for a service
type ServiceType string
const (
// ServiceTypeClusterIP means a service will only be accessible inside the
// cluster, via the ClusterIP.
ServiceTypeClusterIP ServiceType = "ClusterIP"
// ServiceTypeNodePort means a service will be exposed on one port of
// every node, in addition to 'ClusterIP' type.
ServiceTypeNodePort ServiceType = "NodePort"
// ServiceTypeLoadBalancer means a service will be exposed via an
// external load balancer (if the cloud provider supports it), in addition
// to 'NodePort' type.
ServiceTypeLoadBalancer ServiceType = "LoadBalancer"
// ServiceTypeExternalName means a service consists of only a reference to
// an external name that kubedns or equivalent will return as a CNAME
// record, with no exposing or proxying of any pods involved.
ServiceTypeExternalName ServiceType = "ExternalName"
)
安装 Go
安装 IDE 并安装 Go 语言插件
编写一个小程序
给定一个字符串数组
["I","am","stupid","and","weak"]
用 for 循环遍历该数组并修改为
["I","am","smart","and","strong"]
解答
package main
import (
"fmt"
)
func main() {
mylist :=[5]string{"I","am","stupid","and","weak"}
fmt.Println(mylist)
for i, v := range mylist{
//fmt.Println(i, v)
switch v {
case "stupid":
mylist[i]="smart"
case "weak":
mylist[i]="strong"
default:
break
}
}
fmt.Println(mylist)
}