0
点赞
收藏
分享

微信扫一扫

go 命名与包;关于 ++/--;接收键盘输入/终端输入;switch;for 循环;函数;init 函数;匿名函数;闭包;defer;时间日期;内置函数;defer+recover 机制处理错误

月孛星君 2022-01-24 阅读 15

文章目录


  • 命名与包;关于 ++/–;接收键盘输入/终端输入;switch;for 循环;函数;init 函数;匿名函数;闭包;defer;时间日期;内置函数;defer+recover 机制处理错误;数组

  • studygolang.com/pkgdoc

命名与包

  • 变量名、函数名、常量名:采用驼峰命名;

  • 变量名、函数名、常量名, 首字母大写,则可以被其他的包访问;首字母小写,则只能在本包中使用;

  • 导入包需要使用双引号包裹起来;

  • 导入包名是从 $GOPATH/src/ 后开始计算的,路径使用/进行分隔;

  • GOPATH 是一个环境变量需要进行配置;

  • 关键字:25个;预定义标识符:36个,包含基础数据类型和系统内嵌函数;

  • 一般包的声明和所在的文件夹同名;(不同命也没问题)

  • 在函数调用的时候要定位到所在的包;

  • 一个目录下的统计文件不能有不同的 package 名;

  • 一个目录下不能有重复的函数;main 特殊

  • 在程序层面,所有使用相同 package 名的源文件组成一个模块;这也叫解释了上一项函数名不能重复

  • 在(源)文件层面,就是一个文件夹;

  • import ( alais "xxx/xxx/pack") 起个别名;原来的包名不能再用了;

关于 ++/–

  • go 中自操作只能单独使用,不能参与到运算中去;
  • go 中自操作之呢个在变量的后面,不能在前面;写在前面语法错误;

接收键盘输入/终端输入

  • func Scanln(a ...interface{}) (n int, err error);
    • 在换行是才停止扫描;最后一个条码后必须有换行或者到达结束位置;需要使用地址接收参数
  • func Scanf(format string, a ...interface{}) (n int, err error)
    • 要按 format 一样的格式输入内容;

switch

  • switch 后是一个表达式:常量,变量,一个有返回值的函数
  • case 后的表达式如果为常量则不能重复;
  • case 后的数据类型要和 switch 的表达式数据类型一致;
  • case 后可以带多个值,使用逗号分隔;
  • go 的case 后不需要带break;default 也不是必须的,位置也可以随意放置,不一定要在最后;
  • switch 后不带表达式,当作if分支来使用;
  • switch 后可以直接声明一个变量,分号结束
  • 如果需要穿透,使用 fallthrough 关键字,默认只会穿透一个 case;

for 循环

  • for-range 循环 可遍历中文;

函数

  • 函数是go 语言的一等公民;
  • 声明不需要顺序
  • 基本数据类型、数组默认都是值传递;进行值拷贝。在函数内修改,不会影响到原来的值。
  • 函数使用栈帧
  • 如果要在函数内部修改传入的参数并影响入参的变量,可以使用变量的地址&,函数内以指针的方式操作变量。
  • go 中函数也是一种数据类型,可以赋值给一个变量;被赋值的变量就是一个函数类型的变量。通过该变量可以和对函数调用;
  • 函数可以作为形参,并且调用
  • go 和 C 类似的的自定义数据类型:type 自定义数据类型名 数据类型;相当于起了一个别名;
    • type myFunType fun(int, int) int
  • go 支持对函数返回值命名;

init 函数

  • 顺序:1、全局变量的定义;2、init 调用;3、main 调用

匿名函数

  • go 支持匿名函数,如果某个函数只希望使用一次,可以考虑使用匿名函数;
  • 使用方式:
    • 在定义匿名函数时就是直接使用,这种方式匿名函数只能调用一次;
    • 将匿名函数赋值给一个变量,再通过该变量来调用匿名函数;
    • 将一个匿名函数赋值给一个全局变量,可以在整个程序中有效/使用;

闭包

  • 闭包就是一个函数和与其相关的引用环境组合的一个整体;
  • 闭包的本质依旧时一个匿名函数;但是这个函数引入外界的变量/参数
  • 闭包中的变量/参数会一直报存在内存中,所以会一直使用 -> 意味着闭包不可以滥用

defer

  • 延迟执行;
  • defer 后的语句会压入单独的栈;会将相关的值同时拷贝,不会随着函数后面的变化而变化;
  • 用于函数执行完毕后及时释放资源;

时间日期

  • 时间、日期函数,需要导入 time 包
  • 格式化:2006-01-02 15:04:05: 各个数字是固定的必须这样写,自己开发的编程语言,就是这么随意;数字可以自由组合 2006 15:04

内置函数

  • go 设计者为了编程方便,提供了一些函数,这些函数不用导包,可以直接使用,称为go 的内置函数;
  • 内置函数位置:在 buildin 包下;
  • 常用内置函数
    • len: 统计字符串长度,按字节进行统计;
    • new: 分配内存,主要用来分配值类型(int,float,bool,string, 数组,结构体);
    • make: 分配内存,主要用来分配引用类型(指针,slice切片,map,管道chan,interface等);

defer+recover 机制处理错误

  • panic: runtime error:...;
  • func New(text string) error :类似于java 的 new Exception(String text);

数组

  • 定义: var arr [5]int

代码

package main

import (
	"errors"
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

func main() {

	fmt.Println("测试 Scanln 函数")
	var age int
	fmt.Println("input age:")
	fmt.Scanln(&age)
	fmt.Println("age=", age)
	fmt.Println("Scanf input age name:")
	var name string
	_,_ = fmt.Scanf("%d %s", &age, &name)
	fmt.Println("age=", age, ", name=", name)

	fmt.Println(" switch 当作 if 来使用")
	var a int32 = 2
	switch {
	case a == 1:
		fmt.Println("a=1")
	case a == 2:
		fmt.Println("a=2")
		//print("a=2")

	}

	fmt.Println("for 循环 测试")
	var helloStr = "hello str"
	for i := 0; i < len(helloStr); i++ {
		fmt.Printf("%c \n", helloStr[i])
	}

	fmt.Println("for-range 循环 测试")
	for i, val := range helloStr {
		fmt.Printf("idx_is:%d, val_is:%c \n", i, val)
	}
	helloStr += "字符串"
	for i, val := range helloStr {
		fmt.Printf("idx_is:%d, val_is:%c \n", i, val)
	}

	fmt.Println(" 函数测试")
	varFun := test
	fmt.Printf("varFun's type is:%T, test function type is:%T\n", varFun, test)
	varFun(123)
	fmt.Println("go go go ==>>")
	test02(1, 3.14, test)
	test02(1, 3.14, varFun)

	fmt.Println("测试自定义类型")
	type myInt int
	var num1 myInt = 30
	fmt.Println("num1", num1)

	fmt.Println("1、全局变量的定义;2、init 调用;3、main 调用: 测试")
	fmt.Println("globalVar=", globalVar)

	fmt.Println(" 匿名函数 测试")
	res := func(num3 int, num4 int) int {
		return num3 + num4
	}(10, 20)
	fmt.Println("res=", res)

	fmt.Println(" 闭包展示")
	f := getSum()
	fmt.Println(f(1))
	fmt.Println(f(2))
	fmt.Println(f(3))

	fmt.Println(" defer 案例演示:")
	fmt.Println(deferTest(30, 60))

	fmt.Println("===>>>字符串函数:")
	str := "golang中文"
	fmt.Println("str_len=", len(str))

	r := []rune(str)
	for i := 0; i < len(r); i++ {
		fmt.Println(r[i])
	}

	// 字符串转整数:
	num666, _ := strconv.Atoi("666")
	fmt.Println(num666)

	// 整数转字符串:
	str1 := strconv.Itoa(88)
	fmt.Printf("str1_type_is: %T, val_is: %v \n", str1, str1)

	fmt.Println(" 统计字符串中的子串:")
	count := strings.Count("golangandjavaga", "ga")
	fmt.Println(count)
	fmt.Println("不区分大小写的字符串比较:")
	flag := strings.EqualFold("hello", "HELLO")
	fmt.Println(flag)

	fmt.Println("区分大小写的字符串比较:")
	fmt.Println("hello" == "HeLlo")

	// 字符串替换: n=-1表示全部替换;n=2 表示替换两个
	replace := strings.Replace("goandjavagogo", "go", "golang-", 2)
	fmt.Println(replace)

	// 字符串分割 split
	fmt.Println(strings.Split("go-python-java", "-"))

	// 大小写转换
	fmt.Println(strings.ToLower("Go"))
	fmt.Println(strings.ToUpper("go"))

	// 去掉字符串左右两边
	fmt.Println(strings.TrimSpace(" go and  java "))

	// 去掉字符串左右两边指定的字符
	fmt.Println(strings.Trim("##golang@@## ", "#"))
	// 去掉字符串左边指定的字符
	fmt.Println(strings.TrimLeft("##golang@@##", "#"))
	// 去掉字符串右边指定的字符
	fmt.Println(strings.TrimRight("##golang@@##", "#"))
	// 判断是否以指定的字符串开头
	fmt.Println(strings.HasPrefix("https://www.go.com", "http"))
	// 判断是否以指定的字符串结束
	fmt.Println(strings.HasSuffix("https://www.go.com", "cn"))

	fmt.Println("==>> 时间日期函数测试:")
	now := time.Now()
	fmt.Printf("%v ==>> 对应的类型为:%T\n", now, now)

	fmt.Printf("年: %v \n", now.Year())
	fmt.Printf("月: %v \n", now.Month())
	fmt.Printf("月_int: %v \n", int(now.Month()))
	fmt.Printf("日: %v \n", now.Day())
	fmt.Printf("时: %v \n", now.Hour())
	fmt.Printf("分: %v \n", now.Minute())
	fmt.Printf("秒: %v \n", now.Second())

	fmt.Printf("%d-%d-%dT%d:%d:%d \n", now.Year(), now.Month(),
		now.Day(), now.Hour(), now.Minute(), now.Second())
	dateStr := fmt.Sprintf("%d-%d-%dT%d:%d:%d \n", now.Year(), now.Month(),
		now.Day(), now.Hour(), now.Minute(), now.Second())
	fmt.Println(dateStr)

	fmt.Println("使用 Format")
	format := now.Format("2006-01-02 15:04:05")
	fmt.Println(format)
	fmt.Println(now.Format("2006 15:04"))

	fmt.Println("\n内置函数 [new, ]测试")
	num := new(int)
	fmt.Printf("num type is: %T, val is: %v, addr is: %v, 指针指向的值是:%v \n", num,
		num, &num, *num)

	fmt.Printf("\n defer+recover:")
	deferRecover()
	fmt.Println("go-go-go...")
	err := errorsNewTest()
	if err != nil {
		fmt.Println("自定义错误",  err)
		//panic(err)
	}
	fmt.Println("continue-go...")

	fmt.Println("\n 数组测试:")
	var scores [5]int
	scores[0] = 95
	scores[1] = 91
	scores[2] = 39
	scores[3] = 60
	scores[4] = 21

	sum := 0
	for i := 0; i < len(scores); i++ {
		sum += scores[i]
	}
	fmt.Println("sum=", sum)
	var arr [3]int16
	fmt.Println("arr_len_is", len(arr))
	fmt.Println("arr_is:", arr)
	fmt.Printf("arr 地址为:%p \n", &arr)

}

func deferRecover() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("错误已经捕获")
			fmt.Println("err_is:", err)
		}
	}()
	num1 := 10
	num2 := 0
	result := num1 / num2
	fmt.Println(result)
}

func errorsNewTest() (err error){
	num1 := 10
	num2 := 0
	if num2 == 0 {
		return errors.New("除数不能为0!")
	} else {
		res := num1/num2
		fmt.Println(res)
		return nil
	}
}

func deferTest(num1 int, num2 int) int {
	defer fmt.Println("num1=", num1)
	defer fmt.Println("num2=", num2)

	num1 += 10
	num2 += 10
	var sum int = num1 + num2
	fmt.Println("sum=", sum)
	return sum
}

func getSum() func(int) int {
	var sum int = 0
	return func(num int) int {
		sum = sum + num
		return sum
	}
}

func test(num int) {
	fmt.Println(num)
}

func test02(num1 int, num2 float32, funcVar func(int)) {
	funcVar(num1)
	fmt.Println("==>> test02")
}

type funIntType func(int)

func test03(num1 int, num2 float32, funcVar funIntType) {
	funcVar(num1)
	fmt.Println("==>> test03", num2)
}

func addXSub(num1 int, num2 int) (int, int) {
	result01 := num1 + num2
	result02 := num1 - num2
	return result01, result02
}

func addXSub2(num1 int, num2 int) (sum int, sub int) {
	sum = num1 + num2
	sub = num1 - num2
	return
}

var globalVar = varInit()

func varInit() int {
	fmt.Println(time.Now(), ": varInit_call")
	return rand.Int()
}

func init() {
	fmt.Println(time.Now(), ": init_call")
}

输出


2022-01-24 22:05:15.6199452 +0800 CST m=+0.008090501 : varInit_call
2022-01-24 22:05:15.6527917 +0800 CST m=+0.040937001 : init_call
测试 Scanln 函数
input age:
17
age= 17
Scanf input age name:
18
age= 18 , name= 
 switch 当作 if 来使用
a=2
for 循环 测试
h 
e 
l 
l 
o 
  
s 
t 
r 
for-range 循环 测试
idx_is:0, val_is:h 
idx_is:1, val_is:e 
idx_is:2, val_is:l 
idx_is:3, val_is:l 
idx_is:4, val_is:o 
idx_is:5, val_is:  
idx_is:6, val_is:s 
idx_is:7, val_is:t 
idx_is:8, val_is:r 
idx_is:0, val_is:h 
idx_is:1, val_is:e 
idx_is:2, val_is:l 
idx_is:3, val_is:l 
idx_is:4, val_is:o 
idx_is:5, val_is:  
idx_is:6, val_is:s 
idx_is:7, val_is:t 
idx_is:8, val_is:r 
idx_is:9, val_is:字 
idx_is:12, val_is:符 
idx_is:15, val_is:串 
 函数测试
varFun's type is:func(int), test function type is:func(int)
123
go go go ==>>
1
==>> test02
1
==>> test02
测试自定义类型
num1 30
1、全局变量的定义;2、init 调用;3、main 调用: 测试
globalVar= 5577006791947779410
 匿名函数 测试
res= 30
 闭包展示
1
3
6
 defer 案例演示:
sum= 110
num2= 60
num1= 30
110
===>>>字符串函数:
str_len= 12
g 
o 
l 
a 
n 
g 
中 
文 
666
str1_type_is: string, val_is: 88 
 统计字符串中的子串:
2
不区分大小写的字符串比较:
true
区分大小写的字符串比较:
false
golang-andjavagolang-go
[go python java]
go
GO
go and  java
golang@@## 
golang@@##
##golang@@
true
false
==>> 时间日期函数测试:
2022-01-24 22:05:27.8228879 +0800 CST m=+12.211033201 ==>> 对应的类型为:time.Time
年: 2022 
月: January 
月_int: 1 
日: 24 
时: 22 
分: 5 
秒: 27 
2022-1-24T22:5:27 
2022-1-24T22:5:27 

使用 Format
2022-01-24 22:05:27
2022 22:05

内置函数 [new, ]测试
num type is: *int, val is: 0xc00000c548, addr is: 0xc000006030, 指针指向的值是:0 

 defer+recover:错误已经捕获
err_is: runtime error: integer divide by zero
go-go-go...
自定义错误 除数不能为0!
continue-go...

 数组测试:
sum= 306
arr_len_is 3
arr_is: [0 0 0]
arr 地址为:0xc00000c568 

举报

相关推荐

Go 匿名函数与闭包

Go语言——函数与闭包

0 条评论