【狂神说】Go语言零基础学习视频通俗易懂-笔记

本文介绍了Go语言的环境安装,包括GOROOT和GOPATH的设置,以及如何查看Go版本和环境信息。接着讲解了Go的基本语法,如HelloWorld示例,变量声明、初始化和作用域,常量的使用,以及类型转换。还涉及到了位运算符、键盘输入、if和switch语句。此外,文章还涵盖了函数的声明与调用、可变参数、引用传递、延迟执行(defer)和闭包的概念。
摘要由CSDN通过智能技术生成

P3 Go语言环境安装

  1. GOROOT:go的安装目录(例:D:\Environment\Go);
  2. GOPATH:go的工作目录,存放代码的地方(例:D:\Apps\GoWorks);
  3. 工作目录下新建三个文件夹:bin、pkg、src,用于存放之后开发的代码;
  4. 常用命令:
go version 					#查看go版本信息
go env 						#查看go环境配置信息
go env -w GO111MODULE=off	#-w设置env的某个值

P5 HelloWorld

  1. fmt.Println输出时,需要用双引号,不然程序会报错!
  2. GO语言编译的程序都必须有且只能有一个main包(package)和main(func)方法。
package main 	// 必须有

import "fmt"

func main() {	// 必须有
	//打印一句话,打印完后换行
	fmt.Printf("Hello World")
}

P9 什么是变量

  1. 强类型语言,声明数据类型之后不可以更改(PHP低版本可随意更改);
  2. var声明变量,可以声明多个变量,声明的变量一定要使用,不使用会报错

P10 变量初始化

  1. :=自动推导数据类型并赋值

P11 打印内存地址

  1. %p输出类型是地址
  2. &变量名获取变量地址
var num int
num = 100
fmt.Printf("num:%d, 内存地址:%p", num, &num) //取地址符 &变量名
//输出:num:100, 内存地址:0xc0000160b8

P12 变量交换

package main

import "fmt"

func main() {
	var (
		a int = 1
		b int = 2
	)
	//变量交换
	a, b = b, a
	fmt.Println(a, b) //输出 2, 1
}

P13 匿名变量_

  1. _任何赋值给这个标识符的值都将被抛弃
  2. 匿名变量不占用内存空间,不会分配内存
package main

import "fmt"

func test() (int, int) {
	return 100, 200
}

func main() {
	// 对象:User
	a, _ := test()
	_, b := test()
	fmt.Println(a, b) //输出:100, 200
}

P14 变量的作用域

  1. 全局变量:定义在main函数外面,没有其它函数包裹的变量;
  2. 函数内部变量(局部变量)可以和全局变量重名,局部变量优先级高于全局变量;

P15 常量

  1. 常量是一个简单地标识符,在程序运行时,不会被修改的量
  2. 常量字符类型只能是:布尔型、数字型、字符串型;
package main

import "fmt"

func main() {
	const URL string = "www.baidu.com" //显示定义
	const URL2 = "www.baidu.com"       //隐式定义,默认推导数据类型,此处不用加`:`

	const a, b, c = 3.14, "ks", false
	//URL = "wwww" //此处改变变量值会报错:cannot assign to URL
	fmt.Println(URL, URL2)
	fmt.Println(a, b, c)
}

P16 常量iota

  1. iota特殊常量,在const关键字出现时将被重置为0;
  2. 可以叫做:常量计数器;
package main

import "fmt"

func main() {
	const (
		a = iota
		b
		c
		d = 100
		e
		f = "zs"
		g 				// 沿用上一个常量的值
		h = iota
		i
	)

	//在const关键字出现时将被重置为0
	const (
		j = iota
		k
	)
	fmt.Println(a, b, c, d, e, f, g, h, i, j, k) //输出:0 1 2 100 100 zs zs 7 8 0 1
}

P17 布尔类型

  1. Go 语言是一种静态类型的编程语言;
  2. 输出的时候,%T(type):数据类型,%t:(布尔类型)数据的值
package main

import "fmt"

func main() {
	// var 变量名 数据类型
	//bool默认值为false
	var isFlag bool = false
	var isFlag2 bool = true
	//%T type:数据类型
	//%t:数据的值
	fmt.Printf("%T, %t\n", isFlag, isFlag)
	fmt.Printf("%T, %t\n", isFlag2, isFlag2)
}

P18 数字类型

  1. 输出的时候:
    • %d:(int类型)数据的值;
    • %f:(float类型)数据的值;
  2. float32默认是6位小数打印,%.2f:数字表示精度(四舍五入);
  3. 尽量使用 float64 定义float数据,不然精度容易丢失;
package main

import "fmt"

func main() {
	//定义一个整型,%d:(int类型)数据的值
	//byte uint8 0-255,不能有负数、且最大值255
	//rune int32
	//int int64
	var age int = 18
	fmt.Printf("%T, %d\n", age, age)

	//定义一个浮点型,%f:(float类型)数据的值
	var money float32 = 3.1415
	fmt.Printf("%T, %f\n", money, money)
	//默认是6位小数打印,3.141500,%.2f:数字表示精度(四舍五入)
	fmt.Printf("%T, %.2f\n", money, money) //输出:float32, 3.14

	var (
		num1 float32 = -123.0000901 //输出:-123.00009,少了一个精度
		num2 float64 = -123.0000901
		num3 float32 = -1.0000901 //输出:-1.0000901,可以完全输出
	)
	//尽量使用 float64 定义float数据,不然精度容易丢失
	fmt.Println(num1, num2, num3)
}

P19 字符与字符串

package main

import "fmt"

func main() {
	var str string
	str = "Hello!"
	fmt.Printf("%T, %s\n", str, str)

	//单引号 字母,整型-ASCII字符码
	//扩展:
	//所有的中国字的编码表:GBK
	//全世界的编码变:Unicode编码表
	v1 := '中'
	v2 := "A"
	fmt.Printf("%T, %d\n", v1, v1) //输出:int32, 65
	fmt.Printf("%T, %s\n", v2, v2)

	//字符串链接 +
	fmt.Println("Hello" + ", World!")
	//转义字符 \
	fmt.Println("Hello\"World!")
	fmt.Println("Hello\nWorld!") // n 换行
	fmt.Println("Hello\tWorld!") // t 制表符
}

P20 数据类型的转换

  1. 由于Go语言不存在隐式类型转换,因此所有的类型转换都必须是显式的声明;
  2. 转换后的变量 := 要转换的类型(变量), 备注:整型是不能转化为bool类型的;
package main

import "fmt"

// 类型转换
// 转换后的变量 := 要转换的类型(变量)
// 备注:整型是不能转化为bool类型的
func main() {
	a := 3   //int
	b := 5.0 //float64

	//需求:将int类型的a转换位 float64 类型 类型转换
	c := float64(a)
	d := int(b)

	// bool 整型是不能转化为bool类型的
	//e := bool(a)

	fmt.Printf("%T\n", a)
	fmt.Printf("%T\n", b)
	fmt.Printf("%T\n", c)
	fmt.Printf("%T\n", d)
}

P24 位运算符

  1. &&操作两个bool类型变量,&操作二进制值;
  2. %b(binary):二进制形式输出;
package main

import "fmt"

func main() {

	// 二进制 0 1 逢二进一
	// 位运算:二进制上的 0 false, 1 true
	// & 我和你 1 1 结果才为1, 0 1为 0
	// | 我或者你 0 1 为1, 0 0 为 0
	// 60 0011 1100
	// 13 0000 1101
	// ------------
	// &  0000 1100 4+8=12
	// |  0011 1101 1+4+8+16+32=61
	// ^  0011 0001 不同为1,相同为0

	a := 60
	b := 13
	//位运算
	c := 0

	//%b(binary),二进制形式输出
	c = a & b                           //位运算符
	fmt.Printf("%d,二进制:%b \n", c, c) //输出:12,二进制:1100

	c = a | b                           //位运算符
	fmt.Printf("%d,二进制:%b \n", c, c) //输出:61,二进制:111101
	
	c = a >> 2                          //位运算符
	fmt.Printf("%d,二进制:%b \n", c, c) //输出:15,二进制:1111

	c = a << 2                          //位运算符
	fmt.Printf("%d,二进制:%b \n", c, c) //输出:240,二进制:11110000
}

P26 拓展之获取键盘输入

package main

import "fmt"

func main() {

	var x int
	var y float64

	//定义两个变量,用键盘来录入这两个变量
	//fmt.Printf()  // 格式化输出
	//fmt.Println() // 打印并换行
	//fmt.Print()   // 打印输出

	fmt.Println("请输入两个数: 1、正数, 2、浮点数:")
	// 变量取地址 &变量
	// Scanln 阻塞等待你的键盘输入
	fmt.Scanln(&x, &y)
	fmt.Println("x:", x)
	fmt.Println("y:", y)

	//fmt.Scanf() 	//接收输入 格式化输入
	//fmt.Scanln() 	//接收输入 Scan |
	//fmt.Scan() 	//接收输入
}

P27 小结聊聊编码规范

  1. 引入包顺序:
    • 标准库包
    • 程序内部包
    • 第三方包

P29 if语句

package main

import "fmt"

// if 如果。。。否则 else
func main() {

	// 分数
	var score int = 90

	// a b c d
	if score >= 90 && score <= 100 {
		fmt.Println("A")
	} else if score >= 80 && score < 90 {
		fmt.Println("B")
	} else if score >= 70 && score < 80 {
		fmt.Println("C")
	} else if score >= 60 && score < 70 {
		fmt.Println("D")
	} else {
		fmt.Println("不及格")
	}
}

P30 if 多重嵌套

package main

import "fmt"

// if 嵌套语句
func main() {

	// 验证密码, 再次输入密码
	var a, b int
	var pwd int = 20221020
	// 用户的输入
	fmt.Print("请输入密码:")
	fmt.Scanln(&a)

	if a == pwd {
		fmt.Print("请再次输入密码:")
		fmt.Scanln(&b)
		if b == pwd {
			fmt.Println("登录成功!")
		} else {
			fmt.Println("第二次密码错误")
		}
	} else {
		fmt.Println("密码错误")
	}
}

P31 switch语句

package main

import "fmt"

// switch语句
func main() {

	score := 90
	//匹配 case
	switch score {
	case 90:
		fmt.Println("A")
		fallthrough //穿透,继续往下执行 一个 case
	case 80:
		fmt.Println("B")
	case 50, 60, 70:
		fmt.Println("C")
	default:
		fmt.Println("D")
		break // 跳出
	}
	// 输出:A B

	// switch 后面不跟,默认条件 bool = true
	switch {
	case false:
		fmt.Println("false")
		break
	case true:
		fmt.Println("true")
	default:
		fmt.Println("Other")
	}
	// 输出:true
}

P35 打印99乘法表

package main

import (
	"fmt"
)

// 目标:使用for循环打印99乘法表
func main() {
	for j := 1; j <= 9; j++ {
		for i := 1; i <= j; i++ {
			fmt.Printf("%d*%d=%d\t", i, j, i*j)
		}
		fmt.Println()
	}
}

P39 函数的声明和调用

// 函数的声明和调用
package main

import "fmt"

func main() {
	// 函数的调用
	printInfo()

	myPrint("haha!")

	myPrintNum(add2(1, 23))

	a, _ := swap("www", "com")
	fmt.Println(a)
}

// 无参无返回值函数
func printInfo() {
	fmt.Println("printInfo")
}

// 有一个参数的函数
func myPrint(msg string) {
	fmt.Println(msg)
}
func myPrintNum(num int) {
	fmt.Println(num)
}

// 有两个参数的函数
// 有一个返回值的函数
func add2(a, b int) int {
	c := a + b
	return c
}

// 有多个返回值的函数
func swap(a, b string) (string, string) {
	return b, a
}

P41 可变参数

  1. 可变参数需要放到最后;
  2. 一个函数的参数列表中最多只能有一个可变参数;
// 可变参数
package main

import "fmt"

func main() {
	getSum(1, 2, 3, 4)
}

// ...可变参数
func getSum(nums ...int) {
	sum := 0
	for i := 0; i < len(nums); i++ {
		fmt.Println(nums[i])
		sum += nums[i]
	}

	fmt.Println("sum:", sum)
}

P42 引用传递

  1. 值类型的传递(操作的是数据本身):
    int、string、bool、float64、array…
  2. 引用类型的数据(操作的是数据的地址):
    slice(切片:可以扩容的数组)、map、channel…
package main

import "fmt"

// 引用传递
func main() {
	// 切片,可以扩容的数组
	s1 := []int{1, 2, 3}
	fmt.Println("默认的数据:", s1)
	// 传入的是引用类型的数据,地址
	update2(s1)
	fmt.Println("调用后的数据:", s1)
}

func update2(s2 []int) {
	fmt.Println("传递的数据:", s2)
	s2[0] = 100
	fmt.Println("修改后的数据:", s2)
}

输出:

默认的数据: [1 2 3]
传递的数据: [1 2 3]
修改后的数据: [100 2 3]
调用后的数据: [100 2 3]

P46 defer延迟函数执行

  1. 函数执行到最后时,这些 defer 语句会按照逆序执行(类似栈结构)
package main

import "fmt"

// defer 延迟函数
func main() {
	a := 10
	fmt.Println("a=", a)
	defer f(a) // 参数已经传递进去了,在最后执行
	a++
	fmt.Println("end a=", a)
	defer f(a) // 比上面那个defer先执行
}

func f(s int) {
	fmt.Println("函数里面的a=", s)
}

输出:

a= 10
end a= 11      
函数里面的a= 11
函数里面的a= 10

P47 函数本质的探讨

  1. 函数加括号是调用,不加括号是变量
package main

import "fmt"

// 函数本质的探讨
// func() 本身就是一个数据类型
func main() {

	// f3 如果不加括号,函数就是一个变量
	// f3() 如果加了括号那就成了函数的调用
	fmt.Printf("%T\n", f3) // func()| func(int, int)  | func(int, int) int
	//fmt.Printf("%T\n", 10)      // int
	//fmt.Printf("%T\n", "hello") // string

	// 定义函数类型的变量
	var f4 func(int, int)
	f4 = f3 // 引用类型的
	fmt.Println(f4)
	fmt.Println(f3)
	f4(1, 2)
}

func f3(a, b int) {
	fmt.Println(a, b)
}

P48 匿名函数推导

  1. 将匿名函数作为另一个函数的参数,回调函数
  2. 将匿名函数作为另外一个函数的返回值,可以形成闭包结构
package main

import "fmt"

// 匿名函数的推导
func main() {

	f5()
	f6 := f5 // 函数本身也是一个变量
	f6()

	// 匿名函数
	f7 := func() {
		fmt.Println("我是f7函数")
	}
	f7()

	// 匿名函数自己调用自己
	func(a, b int) {
		fmt.Println(a, b)
		fmt.Println("我是f8函数")
	}(1, 2)

	// 匿名函数自己调用自己
	res := func(a, b int) int {
		return a + b
	}(1, 2)
	fmt.Println(res)
}

func f5() {
	fmt.Println("我是f5函数")
}

P49 函数式编程

  1. 高阶函数: 将一个函数座位另外一个函数的参数
package main

import "fmt"

// 函数式编程
func main() {
	r1 := add3(1, 2)
	fmt.Println(r1)

	r2 := oper(3, 4, add3)
	fmt.Println(r2)

	r3 := oper(8, 4, sub)
	fmt.Println(r3)

	r4 := oper(8, 4, func(i int, i2 int) int {
		if i2 == 0 {
			fmt.Println("除数不能为0")
			return 0
		}
		return i / i2
	})
	fmt.Println(r4)
}

// 高阶函数,可以接受一个函数作为参数
func oper(a, b int, fun func(int, int) int) int {
	res := fun(a, b)
	return res
}

func add3(a, b int) int {
	return a + b
}

func sub(a, b int) int {
	return a - b
}

P50 闭包结构的理解

  1. 闭包结构:
    一个外层函数increment()中,有内层函数fun,该内层函数中,会操作外层函数的局部变量i,并且该外层函数increment()的返回值就是这个内层函数fun。这个内层函数fun和外层函数increment()的局部变量i,统称为闭包结构;
  2. 局部变量的生命周期就会发生改变:
    正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁;
  3. 闭包结构中的外层函数的局部变量i并不会随着外层函数increment()的结束而销毁,因为内层函数还在继续使用
package main

import "fmt"

// 闭包结构的理解
func main() {

	r1 := increment()
	fmt.Println(r1)

	v1 := r1()
	fmt.Println(v1)
	v2 := r1()
	fmt.Println(v2)
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	
	r2 := increment()
	v3 := r2()
	fmt.Println(v3)
	fmt.Println(r1())
	fmt.Println(r2())
}

// 自增
func increment() func() int {
	// 局部变量
	i := 0
	// 定义一个匿名函数,给变量自增并返回
	fun := func() int { // 内层函数,没有执行的
		// 局部变量的声明周期发生了变化
		i++
		return i
	}
	return fun
}

问题

  1. GOROOT和GOPATH的区别?
    (一)GOROOT,GOPATH,GOMOD解析、Windows上Go环境配置、常用命令记录
  2. 格式化输出哪些字母代表什么含义?
    Go语言格式化输出,%(占位符)使用
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值