GO圣经初读 | 青训营笔记

42 阅读6分钟

**go圣经中小白认为要重视的点

package main

//包和文件
import (
"fmt" //导入包 必须跟在文件package后 fmt格式化输出、接收输入的函数
//类似于C的include吧 )

//如果包中含有多个.go源文件,它们将按照发给编译器的顺序进行初始化,
//Go语言的构建工具首先会将.go文件根据文件名排序,然后依次调用编译器编译

//每个包都对应一个独立的名字空间
//调用时候要 包名.Func() ex .Println //如果一个名字是大写字母开头的,那么该名字是导出的 感觉很方便啊

//一个包的源代码保存在一个或多个以.go为文件后缀名的源文件

//每个源文件都以一条package声明语句开始 说明该源文件是属于哪个包
//main包比较特殊。它定义了一个独立可执行的程序,而不是一个库。在main里的main 函数 也很特殊,它是整个程序执行时的入口

//开始函数、变量、常量、类型的声明语句(分别由关键字func、var、const、type定义)

//编译器会主动把特定符号后的换行符转换为分号,所以不需要;

//命名规范
//字母数字下划线,作用域
//!开头大小写决定了在包外可见性 大写表示其他包可以使用 这种一般使用长名字 fmt.Printf
//包名字一般小写 驼峰式

// 声明
// 类型声明语句一般出现在包一级,因此如果新创建的类型名字的首字符大写,则在包外部也可以使用
// 变量 var 常量 const 类型 type 函数 func
const boilingF = 212.0

//是在包一级范围声明语句声明
//可在整个包对应的每个源文件中访问

//函数
//函数名字、参数列表(由函数的调用者提供参数变量的具体值)、
//一个可选的返回值列表和包含函数定义的函数体组成。如果函数没有返回值,那么返回值列表是省略的

//变量 var 变量名字 类型 = 表达式
//省略类型 自动推断
//省略表达式 0 false nil -》Go语言中不存在未初始化的变量

// 可以在一个声明语句中同时声明一组变量,或用一组初始化表达式声明并初始化一组变量。
// 如果省略每个变量的类型,将可以声明多个类型不同的变量(类型由初始化表达式推导):
// 包级别声明的变量会在main入口函数执行前完成初始化
var i, j, k int
var b, f, s = true, 2.3, "four"

func test() {
//简短变量声明 name := val
//只能在函数内用
//简短变量声明语句对这些已经声明过的变量就只有赋值行为,但是至少应该有一个没声明的
t, j := 3, 4.4
fmt.Println(t, j)
}

// var声明
var boiling float64 = 100

// 指针
// * &
// 变量一定有指针
// 指针0值-》nil
// 在Go语言中,返回函数中局部变量的地址也是安全的
// 在局部变量地址被返回之后依然有效
func fnode() *int {
var a int = 1
return &a
}

//new
//内建的new函数。表达式new(T)将创建一个T类型的匿名变量,
//初始化为T类型的零值,然后返回变量地址,返回的指针类型为*T
//类似返回函数中创建的对象地址

//变量生命周期 -- 只取决于是否可达
//一个循环迭代内部的局部变量的生命周期可能超出其局部作用域。同时,局部变量可能在函数返回之后依然存在。
//编译器会自动选择在栈上还是在堆上分配局部变量的存储空间,
//这个选择并不是由用var还是new声明变量的方式决定的
//变量逃逸
//Go语言的自动垃圾收集器

// 赋值
// =
// += -+ ...
// ++ -- 成为函数而不是运算,不可以作为右值
// 元组赋值 赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边对应变量的值
// a,b=b,a
// f,err = f() 此处函数返回两个值组成一个元组
// 丢弃值:可以用下划线空白标识符 _ 来丢弃不需要的值
// 隐式赋值 :函数调用传参 函数返回值 复合类型字面量
// 只有右边的值对于左边的变量是可赋值的,赋值语句才是允许的
// !类型必须完全匹配!,nil可以赋值给任何 指针 或 引用 类型的变量。
// 常量 则有更灵活的赋值规则,因为这样可以避免不必要的显式的类型转换
// 是否可以用==或!=进行相等比较的能力也和 可赋值能力 有关系

// 类型 type
// type 类型名字 底层类型
// 类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构
type age int
type money int

// 底层类型相同 ,但是不兼容的 ,无法被比较或运算
// age 是 int 便于区分概念
var ag age = 2
var ai int = 2
var am money = 2

//类型转换
//对于每一个类型T,都有一个对应的类型转换操作T(x),用于将x转为T类型
//运算ag ai am

var end age = ag + age(ai) + age(am) //matchtype

//指针是(int *)(x)
//只有当两个类型的底层基础类型相同时,才允许这种转型操作
//或者是两者都是指向相同底层结构的指针类型,这些转换只改变类型而不会影响值本身
//底层基础类型不同也可转换,但会导致值的改变 double->int
//如果两个值有着不同的类型,则不能直接进行比较

func dataType() {
//整数、浮点数和复数
//int8、int16、int32和int64
//8bit 16bit 32bit 64bit
//uint8、uint16、uint32和uint64
//int、uint和uintptr是不同类型的兄弟类型。其中int和int32也是不同的类型,即使int的大小也是32bit
//在需要将int当作int32类型的地方需要一个显式的类型转换操作
//%取模运算符的符号和被取模数的符号总是一致的,只能用于整数
//整数除法向下取整
//两个相同类型的值可以用==和!=进行比较,不同类型不可以
// 如int 和 bool 不可以
var a int8 = 1
var b int64 = 1
//强制类型转换
if a == int8(b) {
fmt.Println("可以比较")
} else {
fmt.Println("不能比较")
}
//按位运算
//& | ^ 一元:按位取反 二元:按位异或 &^ 位清空
//如果对应y中bit位为1的话,表达式z = x &^ y结果z的对应的bit位为0
//否则z对应的bit位等于x相应的bit位的值。
var aa uint8 = 2
fmt.Println("aa=", aa, "^aa=", ^aa)
fmt.Printf(" aa=%08b \n^aa=%08b\n", aa, ^aa)
// << >> 用0补位

}

func main() {
//var f = boilingF
//
//var c = (f - 32) * 5 / 9
////在main函数内部声明的声明语句声明
//fmt.Printf("boiling point = %g F or %g C\n", f, c)
//
//var a = fnode()
//var b = fnode()
//fmt.Println(a == b)
// fmt.Println("type age, int is" , ai == ag)//报错,age int 类型不同
//c = 2 + 5.5
//var ft gomode.Fahrenheit = 3.3
//fmt.Println(ft)
dataType()
}