循环结构控制、包函数的使用

前言

这里总结的Golang 笔记只适合有点编程基础的人看,比如Java

循环

循环是一段在程序中只出现一次,但可能会连续运行多次的代码。 循环中的代码会运行特定的次数,或者是运行到特定条件成立时结束循环,或者是针对某一集合中的所有项目都运行一次。

for

for循环是一个循环控制结构,可以执行指定次数的循环。

	for init; condition; post { }
    for condition { }
    for { }

for使用

	for i := 0; i < 10; i++{
		for j := 0; j < 10; j++{
			fmt.Println(i)
		}
	}

while实现

Golang中是没有while的,但是可以通过for去实现while这个功能。

	var j = 0
	for j < 10{
		fmt.Printf("%d ", j)
		j++
	}

do…while实现

GoLang中也没有do…while的,也是可以通过for去实现do…while 这个功能。

	var k = 0
	for {
		fmt.Printf("%d ", k)
		if k >= 10 {
			break
		}
		k++
	}

break

这里的意思是for可以一直循环的执行,如果k>= 10的时候它会跳出这个循环,否则的话可以一直执行。

	var k = 0
	for {
		fmt.Printf("%d ", k)
		if k >= 10 {
			break
		}
		k++
	}

label使用

golang中可以和label一起使用,更加容易进行流程控制。注意:这里不建议使用,因为很容易造成流程控制混乱

label1:
	for i := 0; i < 10; i++{
		for j := 0; j < 10; j++{
			fmt.Println(i)
			if j == 2{
				break label1
			}
		}
	}

在这里插入图片描述
从如下的结果可以看出j==2的时候直接跳出双层的for循环了。如果单纯的使用break只能跳出内层的for循环,第二次还是进入内层for循环。

continue

continue是可以进行流程控制,意为跳过本次执行,不影响下次循环执行,也不跳出循环。

	for i:=0; i<10; i++{
		if i == 2{
			continue
		}
		fmt.Println("i:", i)
	}

在这里插入图片描述
从如上结果看出,仅跳过本次执行(i == 2)

goto介绍

  • go语言的goto可以无条件地转移到程序中指定的行。
  • goto语句通常与条件语句配合使用,可以用来实现条件的转移,跳出循环体等功能。
  • goto一般不建议使用,以免造成程序流程的混乱,使维护程序的难度变大。
package main

import "fmt"

func main() {
	fmt.Println("1")
	goto label1
	fmt.Println("2")
	fmt.Println("3")
	fmt.Println("4")
	fmt.Println("5")
	label1:
	fmt.Println("6")
	fmt.Println("7")
}

在这里插入图片描述

包使用

  • 在引用别的包的函数时候需要注意的是,函数名必须是大写,大写是公有的可以被其他包引用,小写是私有不能被其他包使用。

  • 包名与文件夹不一一对应,但是尽量保证二者是一一对应的,一般都是小写的。

  • 在同一个包下,不能有相同的函数名(也不能有相同的全局变量名)。

  • 如果你要编译成一个可执行文件,就需要将包名声明为main。

  • 基本数据类型和数组都是值传递的,进行值拷贝,在函数内修改不会影响原来的值。
    在这里插入图片描述
    这个是包结构如何使用其他go文件中的变量
    main.go

package main

import (
	"fmt"
	"../utils"  // 当前目录
)

func main() {
	fmt.Println(utils.Age)
}

utils.go

package utils

var(
	Age = 10
)

函数

介绍

函数声明包含一个函数名,参数列表, 返回值列表和函数体。如果函数没有返回值,则返回列表可以省略。函数从第一条语句开始执行,直到执行return语句或者执行函数的最后一条语句。在go中函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了,通过该变量可以对函数进行调用。使用函数可以减少代码的冗余,更加容易维护。

函数的结构

func  函数名(形参列表) (返回值列表){
​	代码块
​	return 返回值列表
}

参数

函数定义时指出,函数定义时有参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。但当调用函数,传递过来的变量就是函数的实参,函数可以通过两种方式来传递参数:

  • 值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
func swap(num1 int, num2 int)  {
	tmp := num1
	num1 = num2
	num2 = tmp
}

  • 引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。(这里其实也可以理解是值传递,根本不是引用传递,知识拷贝了一份这个地址 然后使用*ptr 去修改这个值)。
func swap(num1 *int, num2 *int)  {
	tmp := *num1
	*num1 = *num2
	*num2 = tmp
}

多个参数如何传递

  func myfunc(args ...int) {    //0个或多个参数
  }

  func add(a int, args…int) int {    //1个或多个参数
  }

  func add(a int, b int, args…int) int {    //2个或多个参数
  }

注意:其中args是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数.

返回值

"_"标识符,用来忽略函数的某个返回值,Go 的返回值可以被命名,并且就像在函数体开头声明的变量那样使用。返回值的名称应当具有一定的意义,可以作为文档使用。没有参数的 return 语句返回各个返回变量的当前值,相当于java之中void返回,可以去操作一些全局变量,或者引用类型。直接返回语句仅应当用在像下面这样的短函数中。在长的函数中它们会影响代码的可读性。

func cal(num1 int, num2 int) (int, int)  {
	add := num1 + num2
	sub := num1 - num2
	return add, sub
}

命名返回参数可看做与形参类似的局部变量,最后由 return 隐式返回

func add(x, y int) (z int) {
    z = x + y
    return
}

如上代码示例1返回值有两个的时候,当不想使用哪个值的时候可以使用’_'占位符赋值,这里需要注意的是必须保证顺序。

函数类型

在golang之中其实可以理解函数也是一种数据类型,可以给函数传递函数进行使用,也可以去声明函数等操作。

package main

import "fmt"

type myfunc func(int, int) int // 使用函数别名的功能

func main() {
	var num1 = 10
	var num2 = 20
	// 向cal传递add函数
	result := cal(add, num1, num2)
	fmt.Println(result)
}

// 进行相加的操作
func add(num1 int, num2 int) int {
	return num2 + num1
}

// 向函数中传递一个函数
func cal(function func(int, int) int, num1 int, num2 int) int {
	return function(num1, num2)
}

// 使用函数别名
func calus(function myfunc, num1 int, num2 int) int {
	return function(num1, num2)
}

// 预先将两个返回值已经定义好,接受返回值的时候还是要按顺序接收
func cals(num1 int, num2 int) (sum int, sub int) {
	sum = num1 + num2
	sub = num2 - num1
	return // 返回值这里也不需要明确的指定返回什么
}

匿名函数

匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数的优越性在于可以直接使用函数内的变量,不必声明。

func main()  {
	getAdd := func(a, b int) int{
		return a + b
	}
	fmt.Println(getAdd(1,2))
}

闭包

闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。个人理解:在函数1内部的一个函数2引用了他外部变量(函数1中)构成闭包。

// 函数返回的类型 func(int) int
func AddUpper() func(int) int{
	var n = 10
	return func(i int) int {
		n = n + i
		return n
	}
}

func main() {
	// 这里相当于f是一个func(int) int的函数类型
	f := AddUpper() // 这里的f可以理解java语言中对象,每个对象中n对外是私有的所以f1 中的n 和 f2中的n没有任何关系。
	fmt.Println(f(1)) // 11
	fmt.Println(f(2)) // 13
}

通过如上的代码和输出结果可以看出:f可以理解java语言中对象,f对应的函数之中n永远是哪一个所以结果11、13。但是如果f1:= AddUpper()、f2:= AddUpper() 这种情况下是可以进行两个n是不相干的。

defer介绍

1. 关键字 defer 用于注册延迟调用。
2. 这些调用直到 return 前才被执。一般情况是作为释放资源使用(关闭文件、数据库连接、网络连接等)。
3. 多个defer语句从上到下一次放入栈中,执行的时候出栈。
4. defer语句中的变量,在defer声明时就决定了。
func main() {
	test(10, 20)
}

func test(num1 int, num2 int) int {
	defer fmt.Println("num1:", num1)// 如果下面进行赋值等变更的操作,这里值的结果不受任何影响
	defer fmt.Println("num2:", num2)
	sum := num1+num2
  	  num1++
        num2++
	fmt.Println("sum:", sum)
	return sum
}
// 输出的结果: sum: 30 num2: 20 num1: 10

从如上的输出结果之中可以看出,上面的介绍,从上到下入栈,输出出栈。

常见函数

字符串函数

常见的字符串处理函数一般都在 “strconv”,"strings"这两个包之中。

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

func main() {
	var str = "hello world"
  	  // 字符串的长度
	fmt.Println(len(str))

	// 遍历字符串
	num := []rune(str)
	for i:=0; i<len(num); i++ {
		fmt.Printf("%c", num[i])
	}
	fmt.Println()
	fmt.Printf("%T\n", num)

	// 字符串转化为整数
	val, err := strconv.Atoi("123")
	if err!=nil {
		fmt.Println("转换异常")
	}else{
		fmt.Println("转换成功的值为:", val)
	}
	fmt.Printf("%T\n", val)

	// 整数转换为字符串
	strs := strconv.Itoa(123)
	fmt.Println(strs)
	fmt.Printf("%T\n", strs)

	// 字符串转化为 []byte
	var bytes = []byte("hello")
	fmt.Printf("%v\n", bytes)

	// byte转换为字符串
	str1 := string([]byte{97, 98, 99})
	fmt.Println(str1)

	// 获取一个数的二进制
	var i = 10
	j := strconv.FormatInt(int64(i), 2)
	fmt.Println(j)

	// 判断一个字符串中是否包含另外一个字符串
	var str2 = "hello world"
	var str3 = "world"
	flag := strings.Contains(str2, str3)
	fmt.Println(flag)

	// 判断字符串中包含几个char
	nums:=strings.Count("chinese", "e")
	fmt.Println("包含e的个数:", nums)

	//不区分大小写去比较
	flags := strings.EqualFold("abc", "ABC")
	fmt.Println(flags)

	// 返回子串第一次出现的字符串中的位置,找不到返回-1
	indexs := strings.Index("abcdadsadas", "ad")
	fmt.Println(indexs)

	// 返回子串出现在字符串最后的位置
	lastIndex:=strings.LastIndex("addadadadada", "da")
	fmt.Println("最后出现的位置:", lastIndex)

	// 将子串替换成另外的子串最后一个参数是n个old替换为new
	var str4 = "hello go go"
	str4 = strings.Replace(str4, "go", "go语言", 1)
	fmt.Println(str4)

	// 将字符串拆分为字符数组
	arr := strings.Split("hello,world,go,语言", ",")
	for i:=0; i<len(arr); i++{
		fmt.Println(arr[i])
	}
	fmt.Println(len(arr))

	// 字符串进行大小写转换
	var str5 = "sdaAdasfFC"
	str6 := strings.ToUpper(str5)
	str7 := strings.ToLower(str5)
	fmt.Println("转换为大写:", str6, "转换为小写:", str7)

	// 去掉字符串左右两边的空格
	str8 := strings.TrimSpace(" sdd  dssds  d   ")
	fmt.Println(str8)

	// 去掉字符串左右两边指定的字符串 Trimleft TrimRight 去掉左边、右边指定的字符串
	str9 := strings.Trim("hell!", "!")
	fmt.Println(str9)

	// 判断字符串是以什么开头、结尾
	flag2 := strings.HasPrefix("hello", "h")
	flag3 := strings.HasSuffix("hello", "o")
	fmt.Println(flag2, flag3)
}

时间函数

package main

import (
	"fmt"
	"time"
)

func main() {
	// 获取当前时间
	now := time.Now()
	fmt.Printf("当前时间为: %v\nnow的类型为: %T\n", now, now)
	// 获取年
	year := now.Year()
	fmt.Println(year)
	// 这一年过去多少天
	yearDay := now.YearDay()
	fmt.Println(yearDay)
	// 获取月
	month := now.Month()
	fmt.Println(month)
	// 获取日
	day := now.Day()
	fmt.Println(day)
	// 获取年月日 2021 November 27
	date, m, d := now.Date()
	fmt.Println(date,m,d)
	// 获取时
	hour := now.Hour()
	fmt.Println(hour)
	// 获取分
	minute := now.Minute()
	fmt.Println(minute)
	// 获取秒
	second := now.Second()
	fmt.Println(second)
	// 格式化输出,这里打印出你当前的时间
	fmt.Printf(now.Format("2006/01/02 15:04:05"))
}

init函数

每个源文件中都可以有一个init函数,init函数在main函数之前被调用。被go的运行框架优先于main调用。init函数一般的作用是被用来初始化等操作。

package main

import "fmt"

var test int = test1()

func test1() int {
	fmt.Println("test")
	return 90
}

func main() {
	fmt.Println("main")
}

func init()  {
	fmt.Println("init")
}

//执行的结果: test init main

注意:​如果导入包的话,那么优先进行加载包中变量,然后init方法其次是main中变量然后init的方法,剩下的常规执行顺序。

包变量-----包init----main变量----main中init----main方法代码块

如果文章内容有错误,还请大佬们指导,防止误人子弟。继续冲冲冲!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值