Golang基础学习笔记整理,快速了解Golang的基础语法。
学习资料
- 超全golang面试题合集+golang学习指南+golang知识图谱+入门成长路线 ;一份涵盖大部分golang程序员所需要掌握的核心知识.
- 韩顺平的golang视频教程 ,视频在B站上,最好倍速播放。
- go语言环境配置
- Go 包网站 golang.com.cn是中文版本的 Go 包网站。 golang.org 是Go开源项目的主站, 而 golang.com.cn 集中为Go用户提供了丰富的资源和文档,是Go生态重要的一环。
一、开发环境配置
golang的安装非常简单,直接从golang的官网上下载对应系统的安装包直接安装即可;不过golang的官网:https://golang.org 国内由于特殊原因无法访问;因此请使用这个:https://golang.google.cn/ 。
Windows和Mac安装直接根据安装界面一路next下去即可;唯一需要注意的是安装路径问题,如果不想用默认的可以修改安装路径(Windows的建议换一个没有空格的目录)。安装成功后输入go version
即可看到安装的版本。Mac 默认安装在/usr/local/go
目录下。
由于国内网络原因,有些包无法下载;因此需要配置GOPROXY来解决问题;即在环境变量里面配置添加GOPROXY的配置;下面是一些可用的国内源配置:
- 阿里云的
https://mirrors.aliyun.com/goproxy/
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/
- goproxy.io提供的服务
https://goproxy.io/zh/
# 配置 GOPROXY 环境变量
go env -w GOPROXY=https://goproxy.io,direct
# 还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
export GOPRIVATE=git.mycompany.com,github.com/my/private
二、常用命令
编译
go build go文件名称
# 自定义生成的exe文件名称
go build -o 自定义名字.exe go文件名称
# 示例
go build hello.go
go build main.go
go build -o hello.exe hello.go
运行程序
go run hello.go
格式化文件
gofmt -w hello.go
运行测试
go test -v
查看环境变量配置
go env
查看资源竞争情况
go build -race demo.go
三、基础语法和概念
这个基本和其他语言没有太大的差别,不同之处在于:golang的定义是将类型写变量的后面,同时不支持自动类型转换需要手动转换;包含的基础类型:bool、float32、float64、string、byte(uint8)、int、int8、int16、int32、int64、rune(int32,常用来处理unicode或utf-8字符);其他类型的切片、结构体、函数、接口、map。同时golang不需要在语句末尾写符号。
注意事项
- 区分大小写;
- 可以不写分号;
- 定义或引入了的必须使用;
- 一个文件夹下的.go文件中只能有一个main函数;
- 不支持隐式转换;必须显示转换;
- 函数不支持重载
- 结构体中为属性的分配的地址是连续的
- 结构体是使用的值传递
- 结构体进行强制转换的时候需要2个结构体的属性都相同才可以
定义变量
语法如下,注意golang会自动设置初始值。
// 声明变量不赋值,将使用默认值, int 默认值为0
var a int
// 声明变量并赋值
var b int = 10
// 简化var关键词的写法
c := 100
// 根据值自动判断变量类型
var d = 10
// 一次性声明多个类型相同的变量
var n1, n2, n3 int
// 一次性声明多个变量,且类型不同
var age, nickName, addr = 10, "jerry", "北京"
// 一次性声明多个变量,简写var关键词
email, phone, pwd := "1314@qq.com", 9580, "123456"
// 声明多个全局变量时可以直接用一个var包裹
var (
ok_status = "ok"
ok_code = 200
)
// 如果字符在ascii表,则可以直接使用byte
var ch byte = 'a'
fmt.Println(ch)
var ch2 int = '蒲'
fmt.Println(ch2)
fmt.Printf("%c", ch2)
// rune处理unicode或utf-8字符;因为string底层使用的byte存储的,因此可以通过rune来解决中文问题
arr2 := []rune(str)
arr2[1] = '李'
str = string(arr2)
fmt.Println("str=", str)
字符串注意事项
注意字符串一旦赋值后就不能修改了,比如下面的这样是错误的
// 字符串赋值后不能修改
var str string = "help"
str[0] = 'a'
字符串拼接直接使用 + 即可;但是需要注意的是golang如果需要换行 + 必须放在上一行;如下:
// 需要把加号放到后面
var str4 = "hello" +
"word"
fmt.Println(str4)
数组的定义
数组在定义时就必须设置大小;不同空间大小的数组的类型是不一样的;注意:在函数中传递数组时,进行的是值传递;要和切片区分开。
var arr [6]int
arr[0] = 5
var arr1 [3]int = [3]int{
1, 2, 3}
fmt.Println("arr1=", arr1)
var arr2 = [3]int{
4, 5, 6}
fmt.Println("arr2=", arr2)
// 这里的...是固定写法;最终大小根据后面设置的初始值个数决定
var arr3 = [...]int{
7, 8, 9}
fmt.Println("arr3=", arr3)
var arr4 = [...]int{
1: 10, 0: 11, 2: 12}
fmt.Println("arr3=", arr4)
// 二维数组
var arr [6][6]int
arr[1][2] = 1
切片的定义
golang中的切片可以简单的认为就是一个动态扩容的数组。切片在底层分配的内存是连续的。
// 切片的定义和数组的很像,不指定大小
var slice []int
// 注意没有赋初始值的切片,必须通过make方法申请空间
slice = make([]int, 0)
// 赋初始值的切片
var slice2 []string = []string{
"tom","jerry"}
// 从一个数组或者是切片中截取一段数据
arr := [...]int{
1, 2, 3, 4}
// [1:3] 表示引用arr数组下标1到3的值(不包含3)
slice := arr[1:4]
// [:]这样表示拿全部;同时切片可以再切片
slice := arr[:]
// 查看slice的元素个数
fmt.Println("slice的元素个数:", len(slice))
// 查看slice的容量
fmt.Println("slice的容量", cap(slice))
// 添加新的元素到切片中
slice = append(slice, 40)
// 添加多个新的元素到切片中
slice = append(slice, 50, 60, 70)
arr[1] = 100
函数变量定义和使用
golang的函数也是一种变量,因此可以将函数也赋值给变量;写法其实和js的语法很像。下面是示例:
package main
import (
"fmt"
"strings"
)
// 累加
func AddUpper() func (int) int {
var n int = 0;
return func (x int) int {
n = n+x;
return n;
}
}
// 判断是否包含后缀
func makeSuffix(suffix string) func (string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
// 将AddUpper函数赋值给变量f;即可通过f调用(有点像取了个别名)
f := AddUpper()
fmt.Println(f(1))
suffix := makeSuffix(".jpg")
fmt.Println(suffix("1.png"))
fmt.Println(suffix("1.jpg"))
}
map
// 申明map
var a map[string]string
// map 需要手动分配初始空间
a = make(map[string]string, 2)
// 赋值
a["no1"] = "张三"
// 定义的时候就分配空间
var map2 = make(map[string]string, 10)
map2["s1"] = "100"
fmt.Println(map2)
// 定义的时候就赋值
map3 := map[string]string {
"address":"成都",
}
fmt.Println(map3)
// map<string, map>的结构
map4 := make(map[string]map[string]string, 2)
map4["001"] = make(map[string]string, 1)
map4["001"]["name"] = "jerry"
map4["001"]["age"] = "26"
map4["002"] = map3
fmt.Println(map4)
// 删除map中的值
delete(map4, "002")
// 如果想删全部的key,需要一个个的遍历来删除;或者重新开辟个空间
for k, _ := range map4 {
delete(map4, k)
}
// 重新开辟个空间
map4 = make(map[string]map[string]string)
// map的查找, key 存在ex为true
val, ex := map3["address"]
fmt.Println(val, ex)
// map 切片的使用
var map5 []map[string]string
map5 = make([]map[string]string, 2)
// 这里不建议使用具体的数组下标来处理,因为容易越界
if map5[0] == nil {
map5[0] = make(map[string]string, 2)
map5[0]["name"] = "唐僧"
map5[0]["store"] = "1000"
}
// 对应动态增加的,推荐使用下面这种方式
newMap := map[string]string {
"name":"悟净",
"store": "5000",
}
map5 = append(map5, newMap)
fmt.Println(map5)
// map的遍历
for k, v := range map6 {
fmt.Println(k, "--", v)
}
// map 排序
map6 := map[int]int{
1:1, 2:2, 4:4, 3:3,}
var keys []int
for k, _ := range map6 {
keys = append(keys, k)}
for k, v := range map6 {
fmt.Println(k, "--", v)}
sort.Ints(keys)
fmt.Println(keys)
结构体
type Person struct {
Name string
Age int
}
// 使用
p2 := Person{
"jerry", 26}
// 定义指针类的
var p3 *Person = new(Person)
(*p3).Name = "tom"
// golang的设计者为让开发者使用方便,可以直接这样写
p3.Age = 26
fmt.Println(*p3)
// 定义指针类的
var p4 *Person = &Person{
}
(*p4).Name = "tj"
// golang的设计者为让开发者使用方便,可以直接这样写
p4.Age = 0
fmt.Println(*p4)
// 定义指针类的简化写法
p5 := &Person{
Name: "jerry", Age: 100}
p5.Age = 26
fmt.Println(p5)
// 为json序列化时设置别名
type Message struct {
Type string `json:"type"`
Data string `json:"data"`
}
类型的转换
golang不支持隐式转换;必须显示转换。
var a int = 100
var b float32 = float32(100)
var c int = 100
var d int32 = int32(100)
基于 fmt.Sprintf方法实现类型转换
var str string
// int 转string
var num1 int = 99
str = fmt.Sprintf("%d", num1)
fmt.Println(str)
// float转string
var num2 float64 = 23.456
str = fmt.Sprintf("%f", num2)
fmt.Println(str)
// bool转string
var b bool = true
str = fmt.Sprintf("%t", b)
fmt.Println(str)
// byte转string
var myChar byte = 'h'
str = fmt.Sprintf("%c", myChar)
fmt.Println(str)
fmt.Printf("str type %T, str=%q", str, str)
// byte数组转string
arr1 := []byte(str)
arr1[0] = 'z'
str = string(arr1)
fmt.Println("str=", str)