0.基本概念

概述

Go语言没有类和继承的概念,所以它和 Java 或 C++ 看起来并不相同。但是它通过接口(interface)的概念来实现多态性。很多重要的开源项目都是使用Go语言开发的,其中包括 Docker、Go-Ethereum、Thrraform 和 Kubernetes。

Go 是编译型语言

Go 使用编译器来编译代码。编译器将源代码编译成二进制(或字节码)格式;在编译代码时,编译器检查错误、优化性能并输出可在不同平台上运行的二进制文件。要创建并运行 Go 程序,程序员必须执行如下步骤。
使用文本编辑器创建 Go 程序;
保存文件;
编译程序;
运行编译得到的可执行文件。
这不同于 Python、Ruby 和 JavaScript 等语言,它们不包含编译步骤。Go 自带了编译器,因此无须单独安装编译器。

内存分配

内存分配器完整保留了 tcmalloc 的原始架构。使用 cache 为当前执行线程提供无锁分配,多个 central 在不同线程间平衡内存单元复用。在更高层次里,heap 则管理着大块内存,用以切分成不同等级的复用内存块。快速分配和二级内存平衡机制,让内存分配器能优秀地完成高压力下的内存管理任务。

变量声明

var name type
go的基本数据类型如下:

  • bool
  • string
  • int、int8、int16、int32、int64
  • uint、uint8、uint16、uint32、uint64、uintptr
  • byte // uint8 的别名 rune //
  • int32 的别名 代表一个 Unicode 码 float32、float64 complex64、complex128

变量被声明之后,系统自动赋予它该类型的零值:

  • 整型和浮点型变量的默认值为 0 和 0.0。
  • 字符串变量的默认值为空字符串。
  • 布尔型变量默认为 false。
  • 切片、函数、指针变量的默认为nil。

除 var 关键字外,还可使用更加简短的变量定义和初始化语法。 名字 := 表达式,简短模式有以下限制:

  • 定义变量,同时显式初始化。
  • 不能提供数据类型。
  • 只能用在函数内部。
    注意:由于使用了:=,而不是赋值的=,因此推导声明写法的左值变量必须是没有定义过的变量。若定义过,将会发生编译错误。
    // 声明 hp 变量
    var hp int
    // 再次声明并赋值
    hp := 10
    编译会报错
    i, j := 0, 1 也支持这种同时多个变量赋值

变量初始化的标准格式:
var 变量名 类型 = 表达式 var hp int = 100
var hp = 100 将 int 省略后,编译器会尝试根据等号右边的表达式推导 hp 变量的类型。

匿名变量
匿名变量的特点是一个下画线“”,“”本身就是一个特殊的标识符,被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃,因此这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其它变量进行赋值或运算。使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。例如:

func GetData() (int, int) {
    return 100, 200
}
func main(){
    a, _ := GetData()
    _, b := GetData()
    fmt.Println(a, b)
}
//运行结果100 200  匿名变量不占用内存空间,不会分配内存。匿名变量与匿名变量之间也不会因为多次声明而无法使用。

变量的作用域

  1. 局部变量
    在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量
    形式参数会作为函数的局部变量来使用
func main() {
    //声明局部变量 a 和 b 并赋值
    var a int = 3
    var b int = 4
    //声明局部变量 c 并计算 a 和 b 的和
    c := a + b
    fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}
//a = 3, b = 4, c = 7
  1. 全局变量
    在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用
//声明全局变量
var c int
func main() {
    //声明局部变量
    var a, b int
    //初始化参数
    a = 3
    b = 4
    c = a + b
    fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}
//a = 3, b = 4, c = 7
//Go语言程序中全局变量与局部变量名称可以相同,但是函数体内的局部变量会被优先考虑。

一些类型说明

  1. 程序逻辑对整型范围没有特殊需求。例如,对象的长度使用内建 len() 函数返回,这个长度可以根据不同平台的字节长度进行变化。实际使用中,切片或 map 的元素数量等都可以用 int 来表示。反之,在二进制传输、读写文件的结构描述时,为了保持文件的结构不会受到不同编译目标平台字节长度的影响,不要使用 int 和 uint。

  2. Go语言中不允许将整型强制转换为布尔型,代码如下
    var n bool
    fmt.Println(int(n) * 2) 报错

  3. Go语言的字符有以下两种:
    一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。
    另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。

  4. Go没有隐式类型转换,所有转换必须显示进行。类型 B 的值 = 类型 B(类型 A 的值) a := 5.0 a := 5.0;类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int32 转换为 int16 或将 float32 转换为 int),会发生精度丢失(截断)的情况。只有相同底层类型的变量之间可以进行相互转换(如将 int16 类型转换成 int32 类型),不同底层类型的变量相互转换时会引发编译错误(如将 bool 类型转换为 int 类型)

指针

默认值是nil,每个变量在内存中都有它的地址,指针通过取地址操作符获得变量或者对象的地址,ptr := &v // v 的类型为 T。ptr 的类型为T。ptr := new(string),也可以定义指针变量。通过解引用操作符可以操作指针变量,同时修改指向对象的值。*ptr = xxx;指针和c/c++很像。
go run -gcflags “-m -l” -gcflags 参数是编译参数。其中 -m 表示进行内存分配分析,-l 表示避免程序内联,也就是避免进行程序优化,通过这个可以查看程序运行,变量内存分配情况
变量逃逸:c/c++程序需要关心各种内存分配,是在栈上还是在堆上,go致力于把程序员从这种痛苦中解救出来。变量是否被取地址,是否发生逃逸,编译器自动选择如何处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值