Go 语言之变量与循环

Go 语言学习笔记

一、如何以及为什么要配置Go语言环境变量?

为了系统能在任何目录下都可以执行 go 指令,go 的指令在 go/bin 目录下。

命名内容
GOROOTGo 的安装目录
Path指定 bin 目录,为了能找到 go 指令
GOPATH项目的工作路径. Java 没有这个

Mac 下配置环境变量方法
Vim .bash_profile 打开文件
i 进入编辑
esc 退出编辑
:wq 保存并退出
$PATH:user $ 代表引用 path 路径,: 代表追加。

go env  进入 go 环境配置
go env -w GOOS=“linux”   修改 go 环境配置

二、变量

  • 无 char 类型,使用 byte 保存单个字符,byte 与 uint8 等价
  • 字符串 string 划分到基本数据类型中
  • int8 有符号整数,0正 1负。 全 0 出现 +0,-0,规定 -0 为-128
  • 浮点数有可能精度损失,原因是尾数可能丢失
  • 传统的字符串由字符组成,而 Go 的字符串由字节组成
  • 字符串一旦赋值了,在 Go 中是不可改变的
  • bool 占用 1 个字节,不可以用 0 或 非0 替代 false 和 true
  • Go语言统一使用 utf-8 编码,英文字母占 1 个字节,汉字占 3 个字节
  • byte类似uint8,rune类似int32,int与uint一样大小(取决于系统),uintptr无符号整型,存放指针

1.类型自动推倒

代码如下(示例):

a := 10     // a 为 int
b := 20.2	// b 为 float64
var c = 10  // 省略数据类型,数据类型自动推倒,c 为int

2.byte

var a byte = 'a'
fmt.Println(a)          // 输出 97
fmt.Printf("%c",a)      // 输出 a
var b = 'a' + 10        // b = 107

3.类型转换

数据类型转换不能自动转换

var a float32 = 10        // 错误       
var b float32 = float32(10)
  1. 基本数据类型转 string
//建议使用第一种方式
var a int = 10
var b = fmt.Sprintf("%d", a).    //%d 代表以十进制输出的字符串,%t bool 类型输出,以此类推
fmt.Printf("%T,%v", b, b)        //%T 值的类型,%v 值的默认格式输出

//第二种方式
var a int = 99
var b = strconv.FormatInt(int64(a),10) //表示十进制
  1. string 转基本数据类型
var str = "10"
var a, _ = strconv.ParseInt(str, 10, 64)  //十进制输出,int64 无溢出类型,_ 是将返回值忽略  
fmt.Println(a)

4.指针

1.基本数据类型变量存的是值,也称为值类型,指针类型变量存的是值的地址。
2.值类型变量直接存储值,栈中分配。引用类型变量存储地址,在堆中分配,当没有变量引用这个地址时,会成为垃圾被回收。

var i int = 10
//p 是一个指针变量
//p 的类型是 *int
//p 本身的值是&i
//*p 是取出 p 所指向的值
var p *int = &i

三、循环控制语句

1.for 循环

    //第一种写法
	for i := 0; i < 10; i++ {
		fmt.Println("学习 Go 语言")
	}
	
	//第二种写法
	j := 5
	for j < 10 { //只写循环条件
		fmt.Println("学习 Go 语言!")
		j++
	}
	
	//第三种写法,无限循环,通常配合 break 使用
	for { //等价 for;;{}
		if j < 15 {
			fmt.Println("学习 Go 语言!!")
		} else {
			break
		}
		j++
	}

    //以字节为单位遍历字符串,一个汉字占三个字节所以会乱码
	var str2 string = "hello go 北京"
	for i := 0; i < len(str2); i++ {
		fmt.Printf("%c\n", str2[i])
	}
	//以字符单位遍历字符串,含有汉字不会乱码
	for index, val := range str2 {
		fmt.Printf("%d %c\n", index, val)
	}

四、函数

1.在import时,路径从$GOPATH/src下开始,所以按照规范在src文件夹下创建工程
2.在调用一个函数时,会给函数分配一个新的内存空间,编译器会将新的内存空间与其他栈空间区分,函数执行完毕后,程序会销毁这个函数对应的空间
3.基本数据类型和数组默认是值传递,即进行值拷贝。也可以传入变量的地址,类似于引用。
4.当执行 defer 时,暂时不执行,会将 defer 后面的语句包括相关的值会拷贝压入独立的 defer 栈,最后执行

type mySum func(int int) int         //相当于一个别名 

var Age int = 20      //ok  
Name := "tom"         //错误,var Name string  Name = "tom" 赋值语句不能在函数体外
func main(){
  	a := getSum                     //函数也是一种数据类型,可赋值给变量
	res := a(10, 30)
	res2 := myFun(getSum, 20, 40)  //函数作为形参
	fmt.Printf("a 的类型%T,getSum的类型是%T\n", getSum, a) //类型:func(int int)int
	fmt.Println("求和的结果是", res, res2)
	//闭包
	f := addUpper()   //返回一个匿名函数,类型func (int) int,与函数外n构成闭包
	fmt.Println(f(1)) //闭包类似于一个类,n 类似字段
	fmt.Println(f(2)) //反复调用f,n 只初始化一次,关键是分析函数与哪些变量构成闭包
}

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

//函数可以是一种数据类型,因此函数可以作为形参并调用
func myFun(funvar func(int, int) int, num1 int, num2 int) int {
	return funvar(num1, num2)
}

//支持对函数返回值命名
func getSumAndSub(a int, b int) (sum int, sub int) {  //自动创建好了返回值sum和sub
	sum = a + b          // :=  ---->  =
	sub = a - b
	return
}

//定义匿名函数(没有函数名的函数)直接调用
res3 := func (a int,b int) int {
	return a + b
}(10,20)                //()代表调用

//闭包
func addUpper() func(int) int {
	var n = 10
	return func(i int) int {
		n = n + i
		return n
	}
}

//init 函数通常完成初始化工作
//main.go、utils.go 都含有init函数和变量定义执行顺序是什么?
//main.go引用utils.go ,先执行utils.go中变量定义,init函数,再执行main.go中变量定义,init(),main()

1.递归

斐波那契数列1,1,2,3,5,8,13
求第 n 个整数的斐波那契数是多少

func fbn(n int) int {
	if n == 1 || n == 2 {
		return 1
	} else {
		return fbn(n-1) + fbn(n-2)
	}
}

2.字符串函数应用

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	var str = "Hello"
	var strLong = "hello,world,ok,go"
	fmt.Println("字符串长度", len(str))          //按字节返回长度
	n, _ := strconv.Atoi("123")                //字符串转整数
	str2 := strconv.Itoa(123)                  //整数转字符串
	var bytes = []byte(str)                    //字符串转byte,比如写入文件
	str3 := string([]byte{97, 98, 99})         //[]byte转string
	b := strings.Contains(str, "o")            //查找字串是否在指定字符串中
	num := strings.Count(str, "l")             //查找字符串中有几个指定的字串
	b1 := strings.EqualFold(str, "HELLO")      //区分字符串是否相等,不包含大小写
	index := strings.Index(str, "l")           //返回子串在字符串第一次出现的index
	index1 := strings.LastIndex(str, "l")      //返回字串在字符串最后一次出现的index
	str4 := strings.Replace(str, "l", "o", -1) //指定字串替换另外一个字串,-1全部替换
	str5 := strings.Split(strLong, ",")        //按照指定字符对字符串进行分割,将会拆分成字符串数组
	str6 := strings.ToLower(str)               //所有字符串中的字母小写
	str7 := strings.ToUpper(str)               //所有字串串中的字母大写
	str8 := strings.TrimSpace(" hello go  ")   //去掉字符串两边的空格
	str9 := strings.Trim("! hello ! ", " !")   //去掉字符串两边指定的字符
	b2 := strings.HasPrefix("http:", "http")   //判断字符串是否以指定字符开头
	b3 := strings.HasSuffix("a.jpg", "jpg")    //判断字符串是否以指定字符结尾
	fmt.Println("n =", n)
	fmt.Printf("%v\n", str2)
	fmt.Printf("%v\n", bytes)  //对应字符编码[104 101 108 108 111]
	fmt.Printf("%v\n", str3)   //输出abc
	fmt.Printf("%v\n", b)      //true
	fmt.Printf("%v\n", num)    //2
	fmt.Printf("%v\n", b1)     //true
	fmt.Printf("%v\n", index)  //从 0 开始算,输出2
	fmt.Printf("%v\n", index1) //从 0 开始算,输出3
	fmt.Printf("%v\n", str4)   //heooo 全部替换 n==1 heolo,str本身不发生变化
	fmt.Printf("%v\n", str5)   //[hello world ok go]
	fmt.Printf("%v\n", str6)   //hello
	fmt.Printf("%v\n", str7)   //HELLO
	fmt.Printf("%v\n", str8)   //"hello go"
	fmt.Printf("%v\n", str9)   //"hello"
	fmt.Printf("%v\n", b2)     //true
	fmt.Printf("%v\n", b3)     //true
}

3.时间函数应用

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()                        //获取当前时间
	fmt.Printf("now=%v,type=%T\n", now, now) //type=time.Time(提供相关方法)
	//获取当前时间年月日、时分秒
	fmt.Printf("年=%v\n", now.Year())
	fmt.Printf("月=%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-%d %d:%d:%d\n", now.Year(), now.Month(), now.Day(),
		now.Hour(), now.Minute(), now.Second())

	str := fmt.Sprintf("%d-%d-%d %d:%d:%d\n", now.Year(), now.Month(), now.Day(),
		now.Hour(), now.Minute(), now.Second())
	fmt.Println(str) //2022-6-20 17:32:30

	fmt.Printf(now.Format("2006-01-02 15:04:05")) //数字必须固定,格式可以改变
	fmt.Println()
	fmt.Printf(now.Format("01")) //数字必须固定,例要指定月份
	fmt.Println()
	//时间常量,go 语言内置时间常量应用
	i := 0
	for {
		i++
		//time.Sleep(time.Second)            //时间常量1s
		time.Sleep(time.Millisecond * 100)   //100ms
		fmt.Println(i)
		if i == 5 {
			break
		}
	}
	//获取时间戳
	fmt.Printf("%v\n", now.Unix())     //1970.7.1到现在的秒
	fmt.Printf("%v\n", now.UnixNano()) //1970.7.1到现在的纳秒
}

4.内置函数

package main

import "fmt"

func main() {
	num := 10
	fmt.Printf("num的类型%T,num的地址%d,num的值%d\n", num, &num, num)
	//new 用来分配内存,主要分配值类型,比如int,float32
	num1 := new(int)
	//num1的类型 *int   指针类型
	//num1的地址 &num1  地址值
	//num1的值   num1   地址值
	//num1执指向的值 *num1 默认0
	fmt.Printf("num1的类型%T,num1的地址%d,num1的值%d\n", num1, &num1, num1)
}

5.捕获并处理函数异常

package main

import (
	"errors"
	"fmt"
)

func main() {
	test()
	fmt.Println("继续执行")
	test1()
	fmt.Println("自定义错误后续")
}
func test() int {
	//通过defer + recover来捕获和处理异常
	defer func() {
		error := recover() //recover()内置函数,捕获异常
		if error != nil {  //说明捕获到错误
			fmt.Println("error", error)
		}
	}()
	num := 10
	num1 := 0
	return num / num1
}

func test1() {
	err := readConf("conf.ini")
	if err != nil {
		panic(err) //输出自定义错误,并终止程序
	}
}
func readConf(name string) (err error) {
	if name == "config.ini" {
		//读取文件...
		return nil
	} else {
		//返回一个自定义错误
		return errors.New("读取文件错误...")
	}
}

四、注意事项

1.变量名的首字母大写代表是公有的,首字母小写代表是私有的。
2.var a int = i++ //错误,i++ 必须单独使用
3.短路与和短路或
4.不支持三元运算符
5.如果内循环有break,它默认跳出最近的for循环,break 后面可以指定标签,跳出对应的for循环
6.在import时,路径从$GOPATH/src下开始,所以按照规范在src文件夹下创建工程
7.在调用一个函数时,会给函数分配一个新的内存空间,编译器会将新的内存空间与其他栈空间区分,函数执行完毕后,程序会销毁这个函数对应的空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值