Go01-开发环境搭建+注释+基本数据类型+指针+命名规范

发布时间 2023-03-26 13:17:33作者: 行稳致远方

Go01-开发环境搭建+注释+基本数据类型+指针+命名规范

1.Go常用网站

  1. https://www.topgoer.com/,Go学习网站,包含Go基础教程、beego、lris等Go开发常用框架。
  2. Go开发软件下载:https://code.visualstudio.com/,VSCode;https://www.jetbrains.com/zh-cn/go/,GOLand。
  3. https://studygolang.com/dl,Go按照包下载。

2.Go开发环境搭建

  1. https://studygolang.com/dl,下载Go安装包,然后直接下一步安装就行。
  2. 配置Go环境。
# 系统变量中配置GOROOT
GOROOT=D:\go
# 系统变量path中添加
%GOROOT%\bin
# 系统变量中配置GOPATH,GOPATH是保存开发Go代码的地方。
GOPATH=D:\GOPATH
# 用户变量中配置GOPROXY
GOPROXY=https://goproxy.io
  1. 创建Go代码环境。
    1. 在配置Go环境中,配置了GOPATH=D:\GOPATH,后面Go代码就存放在GOPATH中。
    2. 在GOPATH目录(D:\GOPATH)中创建bin、src、pkg文件夹。
    3. GOPATH下创建的src文件夹的两个作用:存放开发的代码;通过go get xxx,获取的代码也会保存到src中,如会将通过go get github.com/garyburd/redigo/redis获取的redis包会放到src下。
    4. 如果GO111MODULE=on、auto,go get会将包下载到GOPATH/pkg/mod,引入时也需要从这个目录引入。如果运行了go env -w GO111MODULE=off,go get会将包下载到GOPATH/src。
    5. GOPATH下的pkg用于保存编译后生成的库文件,如xxx.a。
    6. GOPATH下的bin目录可以保存可执行文件,如果将$GOPATH/bin加入到path变量后,则可以直接使用编译好的程序。

3.Go中的转移字符

package main

import "fmt"

func main() {
	// 1 \t表示一个制表符。1	2
	fmt.Println("1\t2")

	// 2 \n表示换行。
	fmt.Println("1\n2")

	// 3 \\表示一个\。 \
	fmt.Println("\\")

	// 4 \"表示一个"。 "
	fmt.Println("\"")

	// 5 \r,从当前行的最开始输出,会覆盖之前输入的内容。 2
	fmt.Println("1\r2")
}

4.Go中的注释

func main() {

	// 1 行注释。官方推荐使用行注释。
	fmt.Println("1")

	/*
		2 块注释
	*/
	fmt.Println("2")
}

5.Go的代码规范

  1. 可以使用gofmt命令对Go代码进行格式化,如gofmt main.go
  2. Go一行代码尽量不超过80个字符,超过的使用换行展示,保持代码优雅。
  3. Go的代码规范是非常严格的。Go的设计思想:一个问题尽量只有一个解决方法。

6.变量

  1. 变量的初始化、声明和使用。
// 1 声明定义变量
var i int
// 2 给变量赋值
i = 10
// 3 使用变量
fmt.Println(i) // 10
  1. 声明变量的三种方式。
// 1 声明变量时,可以指定变量的类型,但是不赋值,这是将使用默认值。
var a int
fmt.Println(a); // 0

// 2 根据变量的值自动推断变量的类型。
var b = "hello"
fmt.Println(b) // hello

// 3 使用:=定义变量,并给变量赋值,可以省略var关键字声明变量
// c := 10,相当与var c int = 10
c := 10
fmt.Println(c) // 10
  1. 一次性声明多个变量的三种方式。
var a1, a2 int
fmt.Println(a1, a2) // 0 0

var b1, b2 = 1, "tom"
fmt.Println(b1, b2) // 1 tom

c1, c2 := 10, 11.1
fmt.Println(c1, c2) // 10 11.1
  1. 全局变量的声明和初始化。
// 1 声明全局变量。
var m1 = 100
var m2 = 200

// 2 一次性声明多个全局变量。
var (
	n1 = 10
	n2 = 20
)
  1. 变量被定义后类型就不能发生变化。
var d1 = 10
fmt.Println(d1)
// 变量类型发生变化后会报错 constant 10.1 truncated to integer
// d1 = 10.1
fmt.Println(d1)
  1. 变量的默认值,int类型默认值是0,string默认值是空串,小数默认值是0。
var e1 int
var e2 string
var e3 float32
fmt.Println(e1, e2, e3) // 0 0 0

7.Go中的+号

// 加号两边是整数类型,则进行加法运行;加号两边是字符串类型,则进行字符串的拼接。
fmt.Println(1 + 2) // 3
fmt.Println("tom" + "alice") // tomalice

8.Go中的数据类型

  1. 基本数据类型。
    1. 数值类型。
      1. 整数类型。int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、byte、
      2. 浮点类型。float32、float64。
    2. byte,字符类型。
    3. bool,布尔类型。
    4. string,字符串类型。
  2. 派生数据类型。指针、数组、结构体、管道、函数、切片、接口、map。

9.整数类型

  1. 无符号整型。
    1. int8,-128~127,1个字节。
    2. int16,-215~215-1,2个字节。
    3. int32,-232~232-1,4个字节。
    4. int64,-264~264-1,8个字节。
  2. 有符号整型。
    1. uint8 0~255,1个字节。
    2. uint16,0~2^16-1,2个字节。
    3. uint32,0~2^32-1,4个字节。
    4. uint64,0~2^64-1,8个字节。
  3. 整数的其他类型。
    1. int,32位系统4字节,-232~232-1;64位系统8字节,-264~264-1。
    2. uint,32位系统4字节,02^32-1;64位系统8字节,02^64-1。
  4. byte。
// byte,无符号,和uint8等价,0~255,一个字节。使用byte表示一个字符。
var a byte = 'a'
fmt.Println(a) // 97

// 使用byte表示一个汉字时报错,constant 25105 overflows byte。
// var b byte = '我'
// fmt.Println(b) // constant 25105 overflows byte
  1. rune。
// rune,有符号,和int32等价,-2^32~2^32-1,四个字节。
// byte用来表示一个字母,不能用来表示一个汉字;rune,可以用来表示一个汉字。
var c rune = '我'
fmt.Println(c) // 25105
  1. 整形变量的类型的大小。
var d = 100
// fmt.Printf()可以进行格式化输出。
// d的类型是int
fmt.Printf("d的类型是%T\n", d)
var e int64 =  1
// unsafe.Sizeof(),返回变量占用的字节数。
// e占用了8个字节。
fmt.Printf("e占用了%d个字节\n", unsafe.Sizeof(e))

10.浮点类型

  1. 浮点型分为单精度float32和双精度float64。float32,-3.403E38~3.403E38;float64, -1.798E308~1.798E308。
  2. 浮点类型可能会造成精度损失。
var a float32 = -123.1234567
var b float64 = -123.1234567
// -123.12346 -123.1234567
fmt.Println(a, b)
  1. 浮点类型默认是float64。
c := 10.1
// c的类型是float64
fmt.Printf("c的类型是%T\n", c)
  1. 浮点类型的两种表示方式。
// 1 常规表示方法。
d := 0.512
e := .512 // 等价于 0.512
// 0.512 0.512
fmt.Println(d, e)

// 2 科学计数法。
f := 5.12e2 // 等价于 5.12 * 10的二次方。
g := 5.12E2 // 等价于 5.12 * 10的二次方。
h := 5.12e-2 // 等价于 5.12 * 10的负二次方。
// 512 512 0.0512
fmt.Println(f, g, h)

11.字符类型

  1. 字符的输出。
// 1 直接输出一个字符时,会输出该字符对应的数字。
var a = 'a'
fmt.Println(a) // 97

// 2 如果希望输出一个字符,就需要%c对其进行格式化输出。
fmt.Printf("%c\n", a) // a
  1. 字符的默认类型。
b := '1'
// int32
fmt.Printf("%T\n", b)
c := '我'
// int32
fmt.Printf("%T\n", c)
  1. 一个英文字符对应一个字节,一个汉字对应三个字节。http://www.mytju.com/classcode/tools/encode_utf8.asp,查询字符对应的UTF8码值。
  2. 字符类型和整型。
// 1 Go中字符的本质就是整数,直接输出的是该字符对应的UTF-8码值。
e := '我'
fmt.Println(e) // 25105

// 2 对一个整数变量格式化后输出,可以输出给变量对应的unicode字符。
var f int = 22269
fmt.Printf("%c\n", f) // 国

// 3 字符类型相当与一个整数,是可以进行计算的。
var g = 'a' + 10 // a对应的整数为97
fmt.Println(g) // 107

12.bool类型

// 1 bool类型的值只能是true或者false。
var a bool = false
fmt.Println(a) // false

// 2 bool类型只占用一个字节。
fmt.Println(unsafe.Sizeof(a)) // 1

13.字符串类型

  1. 字符串就是一串固定长度的字符连接起来的字符序列;Go中字符串的字节是使用UTF-8编码标识的Unicode文本。

  2. Go字符串是不可变的。

var a1 string = "hello"
a1[0] = 'a' // cannot assign to a1[0] (value of type byte)
  1. Go中字符串的两种表示方式。
// 4.1 双引号表示,双引号会转义\t等转义字符。
var a2 = "a\tb"
fmt.Println(a2) // a	b

// 4.2 反引号表示,反引号会将字符原样输出,不会进行转义,可以防止攻击。
var a3 = `a\tb`
fmt.Println(a3) // a\tb
  1. 字符串拼接。
// 字符串在拼接时,+号要放在上一行的最后,而不能放到下一行。
// +号放在上一行的原因:Go会自动在每行的结束添加分号,如果发现+号在最后,
// 就不会添加分号;而如果+放在下一行,就会给上一行添加分号,但是其实下一行
// 也是有内容的,所以会报错。
var a4 = "hello " +
"world"
fmt.Println(a4) // hello world
// 报错
//var a5 = "hello"
//+ "world"

14.基本数据类型的默认值

// 1 Go中基本数据类型都有默认值,当基本类型的变量没有赋值时就会使用默认值,
// 同时默认值也叫做零值。
var a1 int // 0
var a2 float32 // 0
var a3 float64 // 0
var a4 bool // false
var a5 string // "",空串。
// %v表示原值输出,按照变量的原值输出。
// a1=0,a2=0,a3=0,a4=false,a5=
fmt.Printf("a1=%v,a2=%v,a3=%v,a4=%v,a5=%v\n", a1, a2, a3, a4, a5)
fmt.Printf("a5=%q", a5) // a5=""

15.基本数据类型转换

  1. Go中数据类型转换。
// 1 在Go中数据类型不能自动转换,不同类型的变量直接赋值时需要显示转换。
var a1 int = 200
var a2 int8 = int8(a1) // 显示转换,高精度转换为低精度
var a3 int64 = int64(a1) // 显示转换,低精度转换为高精度
// a2=-56,a3=200
fmt.Printf("a2=%v,a3=%v\n", a2, a3)

// 2 将高精度转换为低精度时,当超过低精度的范围时,编译不会报错,
// 只是转换的结果按位溢出
var b1 int = 300
var b2 int8 = int8(b1)
fmt.Printf("b2=%v\n", b2) // b2=44
  1. 类型转换时的编译错误和按位溢出。
// 1 不同类型的的变量赋值时会报错。
var c1 int32 = 12
var c2 int8
var c3 int64
// 将c1类型为int32,加上常量100(100的类型和c1保持一致为int32),
// 所以计算结果为int32,将int32类型赋值给int8类型的c2就会产生类型不匹配的编译错误。
// 编译错误 Cannot use 'c1 + 100' (type int) as type int8
// c2 = c1 + 100
// 编译错误 Cannot use 'c1 + 100' (type int) as type int64
// c3 = c1 + 100

// 将c1先转换为int8类型,加上常量12(12的类型和c1保持一致为int8),所以最后的
// 计算结果为int8类型,将int8类型赋值给int8是不会报错的。
c2 = int8(c1) + 12
// 转为int64在进行计算。
c3 = int64(c1) + 12
fmt.Println(c2, c3) // 24 24

// 2 运行时超过范围会按位溢出;编译时超过范围直接报错,并且编译不通过。
var d1 int32 = 10
var d2 int8
var d3 int8
// 2.1 运行时超过范围会按位溢出。
// 类型相同的赋值是不会报错的,但是如果超出接受变量的类型范围,是会按位溢出的。
// 编译通过,但是结果不是10+127=137,而是-119,会按位溢出。
d2 = int8(d1) + 127
fmt.Println(d2) // -119

// 2.2 编译时超过范围直接报错,并且编译不通过。
// 先将d1转换为int8,在加上128(128的类型和d1保持一致为int8),编译时会
// 将128转换为int8,报错。
// 编译不通过,Invalid operation: int8(d1) + 128 (cannot convert
// constant 128 to type int8)
// d3 = int8(d1) + 128
fmt.Println(d3) // 0

// 2.3 编译时超过范围直接报错,并且编译不通过。
// 将常量128转换为int8,编译不通过。
// 编译不通过,cannot use 128 (untyped int constant) as int8 value
// in variable declaration (overflows)
var d4 int8 = 128
fmt.Println(d4)

16.基本数据类型转string

  1. 基本数据类型转换为字符串的方式一,fmt.Sprintf()。
var a1 int = 100
var a2 float32 = 10.10
var a3 float64 = 20.20
var a4 bool = false
var a5 byte = 'h'

var a6 string

// 1 整形转换为字符串。
a6 = fmt.Sprintf("%d", a1)
// type=string,a6="100"
fmt.Printf("type=%T,a6=%q\n", a6, a6)

// 2 浮点型转换为字符串。
a6 = fmt.Sprintf("%f", a2)
// type=string,a6="10.100000"
fmt.Printf("type=%T,a6=%q\n", a6, a6)

// %.3f表示将浮点数转换为字符串后保留三位小数。
a6 = fmt.Sprintf("%.3f", a3)
// type=string,a6="20.200"
fmt.Printf("type=%T,a6=%q\n", a6, a6)

// 3 bool转换为字符串。
a6 = fmt.Sprintf("%t", a4)
// type=string,a6="false"
fmt.Printf("type=%T,a6=%q\n", a6, a6)

// 4 字符转换为字符串。
a6 = fmt.Sprintf("%c", a5)
// type=string,a6="h"
fmt.Printf("type=%T,a6=%q\n", a6, a6)
  1. 基本数据类型转换为字符串的方式二,strconv.FormatInt()。
var b1 int = 100
var b2 float32 = 10.10
var b3 float64 = 20.20
var b4 bool = false

var b6 string

// 1 整型转换为字符串。
// 10表示转换为整形的十进制。
b6 = strconv.FormatInt(int64(b1), 10)
// type=string,b6="100"
fmt.Printf("type=%T,b6=%q\n", b6, b6)

// 2表示转换为二进制。
// "1100100"
fmt.Printf("%q\n", strconv.FormatInt(int64(b1), 2))

// 2 浮点型转换为字符串。
// f,表示转换后的格式;10,表示保留10位小数;64表示要转换的浮点型是float64。
b6 = strconv.FormatFloat(float64(b2), 'f', 10, 64)
// type=string,b6="10.1000003815"
fmt.Printf("type=%T,b6=%q\n", b6, b6)

// var b3 float64 = 20.20
// 转换后的格式为e,所以转换后为2.022e+01;保留3位小数;转换float32。
b6 = strconv.FormatFloat(b3, 'e', 3, 32)
// type=string,b6="2.020e+01"
fmt.Printf("type=%T,b6=%q\n", b6, b6)

// 3 bool转换为字符串。
b6 = strconv.FormatBool(b4)
// type=string,b6="false"
fmt.Printf("type=%T,b6=%q\n", b6, b6)

// 4 int转换为字符串。
b6 = strconv.Itoa(10)
// type=string,b6="10"
fmt.Printf("type=%T,b6=%q\n", b6, b6)

17.string转换为基本数据类型

// 1 字符串转换为bool类型
var a1 = "false"
var a2 bool
a2, _ = strconv.ParseBool(a1)
// type=bool,a2=false
fmt.Printf("type=%T,a2=%v\n", a2, a2)

// 2 字符串转换为整形。
var b1 = "123456"
var b2 int64
// 10表示字符串是十进制;64表示转换为int64
b2, _ = strconv.ParseInt(b1, 10, 64)
// type=int64,b2=123456
fmt.Printf("type=%T,b2=%v\n", b2, b2)

// 3 字符串转换为浮点类型。
var c1 = "10.10"
var c2 float64
// 64表示转换为float64
c2, _ = strconv.ParseFloat(c1, 64)
// type=float64,c2=10.1
fmt.Printf("type=%T,c2=%v\n", c2, c2)

// 4 strconv.ParseInt()转换的结果是int64;strconv.ParseFloat()转换的结果是float64。
// 如果需要其他类型,就需要进行变量的类型转换。

// 5 在将字符串转换为对应的类型时,字符串的值必须是有效的。如果字符串的值是无效的,
// 则返回各个类型的默认值,如int系列为0,float系列为0,bool为false。

// 5.1 false strconv.ParseBool: parsing "hello": invalid syntax
fmt.Println(strconv.ParseBool("hello"))
// 5.2 0 strconv.ParseInt: parsing "hello": invalid syntax
fmt.Println(strconv.ParseInt("hello", 10, 64))

18.指针

// 1 &获取变量的地址。
var a1 int = 10
// a1的地址 0xc042008230
fmt.Println("a1的地址", &a1)

// 2 指针的定义。
// 2.1 p1是一个指针变量。
// 2.2 p1的类型是*int。
// 2.3 p1的值是&a。
var p1 *int = &a1
fmt.Println(p1) // 0xc042008230

// 3 获取指针指向地址的值。
fmt.Println(*p1) // 10

// 4 通过指针修改变量的值。
b1 := 10
var p2 *int = &b1
fmt.Println(b1) // 10
*p2 = 100
fmt.Println(b1) // 100

// 5 值类型都有对应的指针类型。如int系列的指针类型为*int;float系列的指针类型为*float;
// bool类型的指针类型为*bool。

19.值类型和指针类型

  1. 值类型包括:int系列、float系列、bool、string、数组和结构体struct。
  2. 引用类型包括:指针、slice切片、map、管道chan、interface。
  3. 值类型和引用类型的区别。
    1. 值类型的变量直接存储的是数据的值,内存通常在栈中分配。
    2. 引用类型的变量存储的是一个地址,地址对应的空间才是真正的数据,内存通常在堆上分配。
    3. 当没有任何变量引用堆上的地址时,该地址对应的空间就会变为一个垃圾,由GC进行回收。

20.标识符命名规范

  1. Go中对变量、方法、函数等命名时使用的字符序列称为标识符。

  2. 标识符的命名规则。

    1. 标识符由26个英文字母大小写、0-9和下划线_组成。
    2. 标识符不能以数组开头。
    3. 标识符中不能包含空格。
    4. 下划线_在Go中是一个特殊的标识符,成为空标识符。空标识符可以代表任何其它的标识符,但是它对应的值会被忽略;空标识符只能作为占位符使用,不能作为标识符使用。
    var _ int = 10
    // 不能使用空标识符,否则报错cannot use _ as value
    // fmt.Println(_)
    
  3. 命名规范。

    1. 包名的命名。包名应该使用小写,多个英文单词之间使用_连接,如all_text。
    2. 变量名、方法名、常量名应该使用驼峰命名法,如myName。
  4. Go中没有public、private这样的访问权限修饰符。如果变量名、方法名、常量名的首字母大写,则可以被其他包访问;如果首字母小写,则只能在本包中使用。即首字母大写是公开的;首字母小写是私有的。