目录


GO的优势

极简单的部署方式

  • 可直接编译成机器码
  • 不依赖其他库
  • 直接运行即可部署

静态类型的语言

  • 编译的时候检查出来隐藏的大多数问题

语言层面的并发

  • 天生的基因支持
  • 充分的利用多核

强大的标准库

  • runtime系统调度机制
  • 高效的GC垃圾回收(3色标记和混合写屏障)
  • 丰富的标准库(加解密 底层库 同步机制 网络通信 数据结构与算法等等)

简单易学

  • 25个关键字
  • c语言简洁基因 内嵌c语法支持
  • 面向对象的特征(继承、多态、封装)
  • 跨平台

大厂领军

  • google facebook
  • 腾讯 docker 百度 运维BFE 京东 云储存
  • 哔哩哔哩 阿里巴巴 新浪 七牛 滴滴 字节 小米 美团

不足

  • 包管理不完善
  • 无泛化类型
  • 所有的Exception都用error来处理
  • 对c的降级处理,并非无缝,没有c降级到asm(汇编)那么完美(序列化问题)

GO语言的强项

  1. 云计算基础设施
    docker、kubernetes、etcd、consul、cloudflare CDN、七牛云存储等

  2. 基础后端软件

  3. 微服务

  4. 互联网基础设施

以太坊、hyperledger等

GO语言的基本轮廓

package main

import "fmt"

func main() {

	fmt.Println("Hello Go!")
}
//编译
 go build Hello.go
./Hello

//或者

//编译并执行
go run Hello.go

//初始化项目
go mod init 项目名

变量

package main

import "fmt"
//声明全局变量 :=不实用
var gA int = 100
var gB string = "100"

func main() {
  //============声明全局变量==================================
	// 声明一个变量 默认值是0
	var a int
	fmt.Println("a=", a)
	fmt.Printf("type of a=%T\n", a)
	//声明一个变量 初始化值
	var b int = 100
	fmt.Println("b=", b)
	fmt.Printf("type of a=%T\n", b)

	var bb string = "abcd"
	fmt.Printf("bb=%s,type of bb =%T\n", bb, bb)

	//在数据初始化的时候,省去数据类型,通过值自动匹配相应的数据类型
	var c = 100
	fmt.Println("c=", c)
	fmt.Printf("type of c=%T\n", c)

	var cc string = "abcdefg"
	fmt.Printf("bb=%s,type of bb =%T\n", cc, cc)
//===================都适用=====================================
  
  
	//最常用的方法 省去var关键字 直接自动匹配
	e := 100
	fmt.Println("e=", e)
	fmt.Printf("type of e=%T\n", e, e)

	f := "abcd"
	fmt.Println(f)
  
  
  //声明多个变量
  var gg, hh int = 100, 200
	fmt.Println(gg, hh)
  
  var kk, ll = 100, "abcd"
	fmt.Println(kk, ll)
  
	var (
		vv int    = 100
		jj int    = 200
		mm string = "mmm"
		zz bool   = true
	)
	fmt.Println(vv, jj, mm, zz)

}

常量与iota

package main

import "fmt"

//常量在go语言中定义枚举类型
const (
	name   = "BearBrick0"
	age1   = 22
	sex    = 1
	height = 175
)

//可以在const() 添加一个关键字 iota 每行的iota 都会默认加1,第一行的iota的默认值是0
const (
	num0 = iota
	num1
	num2
	num3
	num4
)

func main() {
	//常量--只读属性
	//常量赋值之后不能重新在对它赋值
	const length = 100
	const age int = 10

	fmt.Println(length, ",", age)
	fmt.Println(name, age1, sex, height)
	fmt.Println(num0, num1, num2, num3, num4)
}

函数

package main

import "fmt"

func main() {
	c := fool1("abc", 10)
	fmt.Println(c)

	d, e := fool2("abc", 2)
	fmt.Println(d, e)

	f, g := fool3("qwe", 12)
	fmt.Println(f, g)
}

//函数返回一个值
func fool1(a string, b int) int {
	fmt.Println(a)
	fmt.Println(b)
	c := 100
	return c
}

//返回多个
func fool2(a string, b int) (int, int) {
	fmt.Println(a)
	fmt.Println(b)

	return 66, 11
}

//指定形参
//func fool3(a string, b int) (r1,r2 int)
func fool3(a string, b int) (r1 int, r2 int) {
	fmt.Println(a)
	fmt.Println(b)

	r1 = 12
	r2 = 34
	return r1, r2
}

init函数和import导包

在不同包 调用函数

sayHello
//同包 -----》函数小写开头都是私有的方法
sayHello()

//在项目根目录编译 				
go build 绝对路径
//快速运行        			 
go run /Users/wanglufei/Documents/GoStudy
SayHello
//不同包----》函数大写开头都是共有的方法
note.SayHello()


//在项目根目录编译 				
go build 绝对路径
//单个主文件 						
go build 路径
//在项目根目录也可以
go build 路径

Modules包管理

大项目结构

小项目地址

注释

和Java差不多。官方建议单行注释。

转义字符

package main
import (
    "fmt"
)
func main() {
    fmt.Println("str := \"c:\\pprof\\main.exe\"")
}

基本数据类型

Golang中所有的值类型变量常量都会在声明是被分配内存空间并被赋默认值。

Golang 更明确的数字类型命名,支持 Unicode,支持常用数据结构

类型长度(字节)默认值说明
bool1false
byte10uint8
rune40Unicode Code Point, int32
int, uint4或8032 或 64 位
int8, uint810-128 ~ 127, 0 ~ 255,byte是uint8 的别名
int16, uint1620-32768 ~ 32767, 0 ~ 65535
int32, uint3240-21亿~ 21亿, 0 ~ 42亿,rune是int32 的别名
int64, uint6480
float3240.0
float6480.0
complex648
complex12816
uintptr4或8以存储指针的 uint32 或 uint64 整数
array值类型
struct值类型
string""UTF-8 字符串
slicenil引用类型
mapnil引用类型
channelnil引用类型
interfacenil接口
functionnil函数

支持八进制、 六进制,以及科学记数法。标准库 math 定义了各数字类型取值范围。

a, b, c, d := 071, 0x1F, 1e9, math.MinInt16
nilNULL

整型

int8int16int32int64uint8uint16uint32uint64
uint8byteint16shortint64long

浮点型

float32float64IEEE 754float323.4e38math.MaxFloat32float641.8e308math.MaxFloat64

复数

complex64`和`complex128
complex64complex128

布尔值

booltrue(真)false(假)
注意:

    布尔类型变量的默认值为false。

    Go 语言中不允许将整型强制转换为布尔型.

    布尔型无法参与数值运算,也无法与其他类型进行转换。

字符串

(int、bool、float32、float64 等)"ASCII
s1 := "hello"
s2 := "你好"
//多行字符串
s1 := `第一行
       第二行
      第三行
     `
fmt.Println(s1)

反引号间换行将被作为字符串中的换行,但是所有的转义字符均无效,文本将会原样输出。

字符串的常用操作

方法介绍
len(str)求长度
+或fmt.Sprintf拼接字符串
strings.Split分割
strings.Contains判断是否包含
strings.HasPrefix,strings.HasSuffix前缀/后缀判断
strings.Index(),strings.LastIndex()子串出现的位置
strings.Join(a[]string, sep string)join操作

byte和rune类型

组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来,如:

var a := '中'

var b := 'x'

Go 语言的字符有以下两种:

uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。

rune类型,代表一个 UTF-8字符。
runeruneint32runeUnicodeUnicodebyte
// 遍历字符串
func traversalString() {
     s := "pprof.cn博客"
    for i := 0; i < len(s); i++ { //byte
        fmt.Printf("%v(%c) ", s[i], s[i])
    }
     fmt.Println()
    for _, r := range s { //rune
        fmt.Printf("%v(%c) ", r, r)
    }
    fmt.Println()
}

输出:

112(p) 112(p) 114(r) 111(o) 102(f) 46(.) 99(c) 110(n) 229(å) 141() 154() 229(å) 174(®) 162(¢)
112(p) 112(p) 114(r) 111(o) 102(f) 46(.) 99(c) 110(n) 21338(博) 23458(客)
3~4

字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。 rune类型用来表示utf8字符,一个rune字符由一个或多个byte组成。

修改字符串

[]rune或[]bytestring
func changeString() {
        s1 := "hello"
        // 强制类型转换
        byteS1 := []byte(s1)
        byteS1[0] = 'H'
        fmt.Println(string(byteS1))

        s2 := "博客"
        runeS2 := []rune(s2)
        runeS2[0] = '狗'
        fmt.Println(string(runeS2))
    }

类型转换

Go语言中只有强制类型转换,没有隐式类型转换。该语法只能在两个类型之间支持相互转换的时候使用。

强制类型转换的基本语法如下:

T(表达式)

其中,T表示要转换的类型。表达式包括变量、复杂算子和函数返回值等.

比如计算直角三角形的斜边长时使用math包的Sqrt()函数,该函数接收的是float64类型的参数,而变量a和b都是int类型的,这个时候就需要将a和b强制类型转换为float64类型。

func sqrtDemo() {
        var a, b = 3, 4
        var c int
        // math.Sqrt()接收的参数是float64类型,需要强制转换
        c = int(math.Sqrt(float64(a*a + b*b)))
        fmt.Println(c)
    }

指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。

Go语言中的指针

&*

指针地址和指针类型

&(int、float、bool、string、array、struct)*int、*int64、*string

取变量指针的语法如下:

ptr := &v    // v的类型为T

其中:

v:代表被取地址的变量,类型为T
    ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。

举个例子:

func main() {
    a := 10
    b := &a
    fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
    fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
    fmt.Println(&b)                    // 0xc00000e018
}
b := &a

指针取值

&*
func main() {
    //指针取值
    a := 10
    b := &a // 取变量a的地址,将指针保存到b中
    fmt.Printf("type of b:%T\n", b)
    c := *b // 指针取值(根据指针去内存取值)
    fmt.Printf("type of c:%T\n", c)
    fmt.Printf("value of c:%v\n", c)
}

输出如下:

type of b:*int
    type of c:int
    value of c:10
*&*

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:\

1.对变量进行取地址(&)操作,可以获得这个变量的指针变量。
    2.指针变量的值是指针地址。
    3.对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

指针传值示例:

func modify1(x int) {
    x = 100
}

func modify2(x *int) {
    *x = 100
}

func main() {
    a := 10
    modify1(a)
    fmt.Println(a) // 10
    modify2(&a)
    fmt.Println(a) // 100
}

fmt格式字符(fmt verbs)

通用

整数

浮点数

布尔

字符串或byte切片

指针