9 Go 语言循环语句
1, 概念
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。
2, 分类
1. for 循环 : 重复执行语句块
a. 语法:
for init; condition; post {}
for condition {}
for {}
init: 一般为赋值表达式,给控制变量赋初值;
condition: 关系表达式或逻辑表达式,循环控制条件;
post: 一般为赋值表达式,给控制变量增量或减量。
b. 实例
for02.go
package main
import "fmt"
func main() {
sum := 0
for i := 0 ; i <= 10; i++ {
sum += i
}
fmt.Println(sum)
}
for03.go
package main
import "fmt"
func main() {
sum :=1
for ; sum <=10 ; {
sum +=sum
}
fmt.Println(sum)
for sum <= 10 {
sum +=sum
}
fmt.Println(sum)
}
c. For-each range 循环
这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。
实例:
for04.go
package main
import "fmt"
func main() {
strings := []string{"google","runoob"}
for i,s :=range strings {
fmt.Println(i,s)
}
numbers := [6]int{1,2,3,5}
for i,x :=range numbers {
fmt.Printf("第%d位置X的值为 %d\n", i , x)
}
num2 :=[]int{11,22,33}
for i,x :=range num2 {
fmt.Printf("第%d位置X的值为 %d\n" , i , x)
}
str := "abcdefghijk"
for i,x :=range str {
fmt.Printf("第%d位置X的值为 %c\n" , i , x)
}
}
2. 循环嵌套 : 在 for 循环中嵌套一个或多个 for 循环
实例:
for05.go
package main
import "fmt"
func main() {
var i,j int
for i=2; i< 100 ; i++ {
for j=2;j<=(i/j);j++{
if(i%j==0){
break
}
}
if(j > (i/j)){
fmt.Printf("%d 是素数\n",i)
}
}
}
for06.go
package main
import "fmt"
func main() {
for i :=1;i<=9;i++{
for j :=1;j<=i;j++{
fmt.Printf("%d x %d = %d \t",i,j,i*j)
}
fmt.Println()
}
}
3, 循环控制语句
1. 循环控制语句可以控制循环体内语句的执行过程。
2. 分类
break 语句: 经常用于中断当前 for 循环或跳出 switch 语句
用途:
a. 用户跳出当前循环,并开始执行循环之外的语句
b. 在 switch 中跳出 case
c. 在多重循环中,可以用标号 label 标出想要break的循环(label名称可以随便起)
实例:
for07.go
package main
import "fmt"
func main() {
num := 10
for ;num <= 20; num++ {
if num == 15 {
break
}
fmt.Println(num)
}
}
for09.go
package main
import "fmt"
func main() {
// 不使用标记
fmt.Println("------break-----")
for i:=1;i<=3;i++{
fmt.Printf("i:%d\n",i)
for i2 := 11; i2 <= 13 ; i2 ++ {
fmt.Printf("i2:%d\n",i2)
break
}
}
// 使用标记
fmt.Println("------break label-----")
re:
for i := 1; i <= 3 ; i++ {
fmt.Printf("i:%d\n",i)
for i2 :=11 ; i2<=13;i2++ {
fmt.Printf("i2:%d\n",i2)
break re
}
}
}
continue 语句: 跳过当前循环的剩余语句,然后继续进行下一轮循环。
实例
for08.go
package main
import "fmt"
func main() {
num := 10
for ; num<=20 ; num++ {
if num == 15 {
continue
}
fmt.Println(num)
}
}
for10.go
package main
import "fmt"
func main() {
// 不使用标记
fmt.Println("-------continue-------")
for i := 1;i<=3;i++{
fmt.Printf("i:%d\n",i)
for i2:=11;i2<=13;i2++{
fmt.Printf("i2:%d\n",i2)
continue
}
}
// 使用标记
fmt.Println("-------continue label-------")
re:
for i:=1;i<=3;i++{
fmt.Printf("i:%d\n",i)
for i2:=11;i2<=13;i2++{
fmt.Printf("i2:%d\n",i2)
continue re
}
}
}
goto 语句: 将控制转移到被标记的语句。
a. 说明:
goto 语句可以无条件地转移到过程中指定的行。
goto 语句通常与条件语句配合使用。可用来实现条件转移,构成循环,跳出循环体等功能。
但是,在结构化程序设计中一般不主张使用 goto 语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。
b. 实例:
4, 无限循环
1. 如果循环中条件语句永远不为 false 则会进行无限循环,我们可以通过 for 循环语句中只设置一个条件表达式来执行无限循环
2. 实例
for01.go
package main
import "fmt"
func main() {
for true {
fmt.Printf("这是无限循环。\n")
}
}
10 Go 语言条件语句
1, 概念
条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句。
2, 分类
if 语句: if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
实例:
if01.go
package main
import "fmt"
func main() {
a := 10
if a < 20 {
fmt.Printf("a 小于 20\n")
}
fmt.Printf("a 的值为 : %d\n", a)
}
if...else 语句: if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。
实例:
if02.go
package main
import "fmt"
func main() {
var a int = 10
if a < 20 {
fmt.Printf("a 小于 20\n")
} else {
fmt.Printf("a 大于 20\n")
}
fmt.Printf("a 的值为: %d\n",a)
}
if 嵌套语句: 你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。
实例:
if03.go
package main
import "fmt"
func main() {
var a int=100
var b int=200
if a == 100 {
if b == 200 {
fmt.Printf("a 的值为:%d,b 的值为:%d\n",a,b)
}
}
fmt.Printf("a 的值为:%d\n",a)
fmt.Printf("b 的值为:%d\n",b)
}
if04.go
package main
import "fmt"
func main() {
var a int
var b int
fmt.Printf("请输入密码:\n")
fmt.Scan(&a)
if a == 123 {
fmt.Printf("请再次输入密码:")
fmt.Scan(&b)
if b == 123 {
fmt.Printf("密码正确")
} else {
fmt.Printf("密码不正确")
}
}else{
fmt.Printf("密码不正确")
}
}
switch 语句: switch 语句用于基于不同条件执行不同动作。
实例:
switch01.go
package main
import "fmt"
func main() {
var grade string = "B"
var marks int = 90
switch marks {
case 90: grade = "A"
case 80: grade = "B"
case 50,60,70: grade = "C"
default:
grade = "D"
}
switch {
case grade == "A":
fmt.Printf("优秀\n")
case grade == "B", grade == "C":
fmt.Printf("良好\n")
case grade == "D":
fmt.Printf("及格\n")
case grade == "F":
fmt.Printf("不及格\n")
default:
fmt.Printf("差\n")
}
fmt.Printf("你的等级是 %s \n", grade)
}
Type Switch
switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。
实例:
switch02.go
package main
import "fmt"
func main() {
var x interface{}
switch i := x.(type) {
case nil:
fmt.Printf(" x 的类型: %T", i)
case int:
fmt.Printf(" x 的类型:int")
case float64:
fmt.Printf("x 是 float64型")
case func(int) float64:
fmt.Printf("x 是 func(int) 类型")
case bool , string:
fmt.Printf("x 是 bool 或 string 类型")
}
}
fallthrough: 使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。
实例:
switch03.go
package main
import "fmt"
func main() {
switch {
case false:
fmt.Println("1, case 条件为false")
fallthrough
case true:
fmt.Println("2, case 条件为true")
fallthrough
case false:
fmt.Println("3, case 条件为false")
fallthrough
case true:
fmt.Println("4, case 条件为true")
case false:
fmt.Println("5, case 条件为false")
fallthrough
default:
fmt.Println("6, 默认 case")
}
}
从以上代码输出的结果可以看出:switch 从第一个判断表达式为 true 的 case 开始执行,如果 case 带有 fallthrough,程序会继续执行下一条 case,且它不会去判断下一个 case 的表达式是否为 true。
select 语句: select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。
select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
语法描述:
每个 case 都必须是一个通信
所有 channel 表达式都会被求值
所有被发送的表达式都会被求值
如果任意某个通信可以进行,它就执行,其他被忽略
如果有多个 case 都可以运行, Select 会随机公平地选出一个执行。其他不会执行。
否则:
1. 如果有 default 子句,则执行该语句。
2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。
实例:
select01.go
package main
import "fmt"
func main() {
var c1,c2,c3 chan int
var i1,i2 int
select {
case i1 = <-c1:
fmt.Printf("received ",i1, "from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok :=(<-c3):
if ok{
fmt.Printf("received ", i3 , "from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no commuinication\n")
}
}
select 会循环检测条件,如果有满足则执行并退出,否则一直循环检测。
select02.go
package main
import (
"fmt"
"time"
)
func Chann(ch chan int, stopCh chan bool){
var i int
i = 10
for j:=0;j<10;j++{
ch <- i
time.Sleep(time.Second)
}
stopCh <- true
}
func main() {
ch := make(chan int)
c :=0
stopCh := make(chan bool)
go Chann(ch, stopCh)
for {
select {
case c= <-ch:
fmt.Println("Receive",c)
fmt.Println("channel")
case s :=<-ch:
fmt.Println("Receive",s)
case _ = <-stopCh:
goto end
}
}
end:
}
注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
备注:
goroutine: Go语言程序的并发体,channels 是它们之间的通信机制。
11 Go 语言函数
1,描述
函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数。
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,返回类型,和参数。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
2,函数定义
func function_name( [parameter list] ) [return_types] {
函数体
}
func:函数由 func 开始声明
function_name:函数名称,函数名和参数列表一起构成了函数签名。
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
函数体:函数定义的代码集合。
3,实例
func01.go
package main
import "fmt"
func main() {
var a int = 100
var b int = 200
var ret int
ret = max(a,b)
fmt.Printf("最大值是:%d\n", ret)
}
func max(num1 , num2 int ) int{
var result int
if(num1 > num2){
result = num1
} else {
result = num2
}
return result
}
func02.go
package main
import "fmt"
func swap(x,y string )(string,string){
return y,x
}
func main() {
a,b := swap("Google","Runoob")
fmt.Println(a,b)
}
4, 函数参数
函数如果使用参数,该变量可成为函数的形参。
形参就像定义在函数体内的局部变量。
调用函数,可以通过两种方式来传递参数。
值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。
实例:
func03.go
package main
import "fmt"
func main() {
a := 100
b := 200
fmt.Printf("交换前 a 的值为: %d\n",a)
fmt.Printf("交换前 b 的值为: %d\n",b)
swap(a,b)
fmt.Printf("交换后 a 的值为:%d\n",a)
fmt.Printf("交换后 b 的值为:%d\n",b)
}
func swap(x,y int) int {
var tmp int
tmp = x
x = y
y = tmp
return tmp
}
5, 函数用法
函数作为另外一个函数的实参: 函数定义后可作为另外一个函数的实参数传入
func05.go
package main
import (
"fmt"
"math"
)
func main(){
getSquareRoot := func(x float64) float64 {
return math.Sqrt(x)
}
fmt.Println(getSquareRoot((9)))
}
闭包: 闭包是匿名函数,可在动态编程中使用
func06.go
package main
import "fmt"
func getSequence() func() int {
i := 0
return func() int{
i++
return i
}
}
func main() {
nextNumber := getSequence()
fmt.Println(nextNumber())
fmt.Println(nextNumber())
fmt.Println(nextNumber())
nextNumber1 := getSequence()
fmt.Println(nextNumber1())
fmt.Println(nextNumber1())
}
func07.go
package main
import "fmt"
func main() {
add_func := add(1,2)
fmt.Println(add_func())
fmt.Println(add_func())
fmt.Println(add_func())
}
func add(x1,x2 int) func()(int,int) {
i := 0
return func() (int,int){
i++
return i , x1+x2
}
}
func08.go
package main
import "fmt"
func main() {
add_func := add(1,2)
fmt.Println(add_func(1,1))
fmt.Println(add_func(0,0))
fmt.Println(add_func(2,2))
}
func add(x1,x2 int) func(x3 int, x4 int)(int,int,int){
i := 0
return func(x3 int, x4 int)(int,int,int){
i++
return i,x1+x2,x3+x4
}
}
方法: 方法就是一个包含了接受者的函数
func09.go
package main
import (
"fmt"
)
/* 定义结构体 */
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("圆的面积 = ", c1.getArea())
}
/* 该 method 属于 Circle 类型对象中的方法 */
func (c Circle) getArea() float64 {
// c.radius 即为 Circle 类型对象中的熟悉
return 3.14 * c.radius * c.radius
}
注意: go语言没有面向对象开发,但是这个方法配合结构体和面向对象开发类似。
12 Go 语言变量作用域
1, 概念:
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
换句话说:就是这个标识符可以在哪里使用
2,声明:
函数内定义的变量称为局部变量
scope01.go
package main
import "fmt"
func main() {
var a,b,c int
a = 10
b = 20
c = a + b
fmt.Printf("结果: a = %d , b = %d , c = %d",a,b,c)
}
函数外定义的变量称为全局变量
scope02.go
package main
import "fmt"
var g int
func main() {
var a,b int
a = 10
b = 20
g = a + b
fmt.Printf("结果: a = %d , b = %d , g = %d", a,b,g)
}
Go 语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑。
函数定义中的变量称为形式参数
scope03.go
package main
import "fmt"
var a int = 20 ;
func main() {
var a int = 10
var b int = 20
var c int = 0
fmt.Printf("main()函数中 a= %d\n",a)
c = sum(a,b)
fmt.Printf("main()函数中 c=%d\n",c)
}
func sum(a,b int) int {
fmt.Printf("sum()函数中 a=%d\n",a)
fmt.Printf("sum()函数中 b=%d\n",b)
return a + b
}
3,初始化局部和全局变量
不同类型的局部和全局变量默认值为:
int 0
float32 0
pointer nil
13 Go 语言数组
1,概念
Go 语言提供了数组类型的数据结构。
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。
数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。
2,声明数组
Go 语言数组声明需要指定元素类型以及元素个数
var variable_name [SIZE] variable_type
例子
var balance [10] float32
3,初始化数组
实例
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
初始化数组中 {} 中的元素个数不能大于 [] 中的数字。
如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
4,访问数组元素
var salary float32 = balance[9]
实例:
list01.go
package main
import "fmt"
func main() {
var n [10] int
var i,j int
for i=0;i<10;i++{
n[i] = i + 100
}
for j = 0 ; j<10;j++{
fmt.Printf("Element[%d] = %d\n" , j , n[j])
}
var l = [5]int{1,2,3,3,4,}
for m := 0;m<5 ; m++{
fmt.Println(l[m])
}
}
5,更多内容
多维数组 Go 语言支持多维数组,最简单的多维数组是二维数组
a. 初始化二维数组
a = [3][4]int{
{0,1,2,3},
{4,5,6,7},
{8,9,10,11},
}
注意:以上代码中倒数第二行的 } 必须要有逗号,因为最后一行的 } 不能单独一行
实例:
list02.go
package main
import "fmt"
func main() {
var a=[5][2]int{
{0,0},
{1,2},
{2,4},
{3,6},
{4,8},
}
// {4,8}后面逗号不能去掉
for i:=0;i<5;i++{
for j:=0;j<2;j++{
fmt.Printf("a[%d][%d] = %d\n",i,j,a[i][j])
}
}
}
向函数传递数组 你可以向函数传递数组参数
如果你想向函数传递数组参数,你需要在函数定义时,声明形参为数组,我们可以通过以下两种方式来声明:
方式一:
void myFunction(param [10]int){}
方式二:
void myFunction(param []int){}
实例:
list03.go
package main
import "fmt"
func main() {
var balance = [5]int{1000,2,3,17,50}
var avg float32
/* 数组作为参数传递给函数 */
avg = getAverage(balance,5)
/* 输出返回的平均值 */
fmt.Printf("平均值为:%f",avg)
}
func getAverage(arr [5]int, size int) float32 {
var i , sum int
var avg float32
for i=0;i<size;i++{
sum +=arr[i]
}
avg = float32(sum) / float32(size)
return avg
}
14 Go 语言指针
1,概念
Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。
变量是一种使用方便的占位符,用于引用计算机内存地址。
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
一个指针变量指向了一个值的内存地址。
类似于变量和常量,在使用指针前你需要声明指针。
var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有效的指针声明:
var ip *int /* 指向整型 */
var fp *float32 /* 指向浮点型 */
2,内存地址实例
pinter01.go
package main
import "fmt"
func main() {
var a int = 10
fmt.Printf("变量的地址:%x\n" , &a)
}
3,如何使用指针
a. 指针使用流程
定义指针变量
为指针变量赋值
访问指针变量中指向地址的值
b. 实例
pointer02.go
package main
import "fmt"
func main() {
var a int = 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是:%x\n",&a)
/* 指针变量的存储地址 */
fmt.Printf("ip 变量存储的指针地址:%x\n",ip)
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值:%d\n", *ip)
fmt.Printf("*&a 的值:%d\n",*&a)
}
4,Go 空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil 在概念上和其它语言的null/None/nil/NULL一样,都指代零值或空值。
一个指针变量通常缩写为 ptr 。
实例:
pointer03.go
package main
import "fmt"
func main() {
var ptr *int
fmt.Printf("ptr 的值为: %x\n",ptr)
}
空指针判断:
if(ptr != nil) /* ptr 不是空指针 */
if(ptr == nil) /* ptr 是空指针 */
指针更多内容
Go 指针数组: 你可以定义一个指针数组来存储地址
pointerlist01.go
package main
import "fmt"
const MAX int = 3
func main() {
a := []int{10,100,200}
var i int
for i=0;i<MAX;i++{
fmt.Printf("a[%d] = %d\n",i,a[i])
}
}
ptr 为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:
pointerlist01.go
package main
import "fmt"
const MAX int = 3
func main() {
a := []int{10,100,200}
var i int
var ptr [MAX]*int
for i = 0;i<MAX;i++{
ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
}
for i=0;i<MAX;i++{
fmt.Printf("a[%d] = %d\n",i,*ptr[i])
}
}
Go 指向指针的指针: Go 支持指向指针的指针
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址。
指针变量声明格式:
var ptr **int
实例:
pointerlist02.go
package main
import "fmt"
func main() {
var a int
var ptr *int
var pptr **int
a = 3000
ptr = &a
pptr = &ptr
fmt.Printf("变量 a = %d\n",a)
fmt.Printf("指针变量 *ptr = %d\n", *ptr)
fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}
Go 向函数传递指针参数: 通过引用或地址传参,在函数调用时可以改变其值
Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。
实例:向函数传递指针,并在函数调用后修改函数内的值
pointerfunc01.go
package main
import "fmt"
func main() {
var a int = 100
var b int = 200
fmt.Printf("交换前 a 的值: %d \n", a)
fmt.Printf("交换前 b 的值: %d \n", b)
/* 调用函数用于交换值
* &a 指向 a 变量的地址
* &b 指向 b 变量的地址
*/
swap(&a,&b)
fmt.Printf("交换后 a 的值: %d \n", a)
fmt.Printf("交换后 b 的值: %d \n", b)
}
func swap(x *int, y *int){
var tmp int
tmp = *x
*x = *y
*y = tmp
}
15 Go 语言结构体
1,概念
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体表示一项记录,比如保存图书馆的书籍记录。
2,定义结构体
结构体定义需要使用 type 和 struct 语句。 struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。
格式:
type struct_variable_type struct {
member definition
member definition
...
member definition
}
一旦定义了结构体类型,他就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1,value2,...}
variable_name := structure_variable_type {k1:v1,k2:v2,k3:v3}
实例:
struct01.go
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言","www.runoob.com","Go 语言教程", 1826262})
// 也可以使用 k=>v格式
fmt.Println(Books{title:"Go 语言",author:"www.runoob.com",subject:"Go 语言教程",book_id:1826262})
// 忽略的字段为0或空
fmt.Println(Books{title:"Go 语言",author:"www.runoob.com"})
}
3,访问结构体成员
如果要访问结构体成员,需要使用点号.操作符
实例:
struct02.go
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books
var Book2 Books
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 1826262
Book2.title = "Python教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6262182
fmt.Printf("Book1 title: %s\n",Book1.title)
fmt.Printf("Book1 author: %s\n",Book1.author)
fmt.Printf("Book2 title: %s\n",Book2.title)
fmt.Printf("Book2 author: %s\n",Book2.author)
}
4,结构体作为函数参数
你可以像其他数据类型一样将结构体类型作为参数传递给函数。
struct03.go
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books
var Book2 Books
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(Book1)
/* 打印 Book2 信息 */
printBook(Book2)
}
func printBook( book Books ) {
fmt.Printf( "Book title : %s\n", book.title)
fmt.Printf( "Book author : %s\n", book.author)
fmt.Printf( "Book subject : %s\n", book.subject)
fmt.Printf( "Book book_id : %d\n", book.book_id)
}
struct04.go
package main
import "fmt"
type Student struct {
name string
age int
classname string
score int
}
func (s *Student) Totle() int { // 为 Student 类型绑定 Totle的方法。*Student为指针引用,可以修改传入参数的值
return s.score * 5 //方法归属于类型,不归属于具体的对象,声明该类型的对象即可调用该类型的方法
}
func main() {
var stu1 Student
var stu2 Student
stu1.name = "张三"
stu1.age = 24
stu1.classname="初一"
stu1.score = 89
stu2.name = "李四"
stu2.age = 20
stu2.classname = "初二"
stu2.score = 95
fmt.Printf(stu1.name,stu1.age,stu1.classname,stu1.score,stu1.Totle())
fmt.Printf(stu2.name,stu2.age,stu2.classname,stu2.score,stu2.Totle())
}
16 Go 语言切片
1, 概念
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场所中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
2, 定义切片
你可以声明一个未指定大小的数组来定义切片
var identifier []type
切片不需要说明长度
或使用make()函数来创建切片
var slice1 []type = make([]type,len)
也可以简写为
slice1 := make([]type,len)
也可以指定容量,其中capacity为可选参数
make([]T,length,capacity)
这里 len 是数组的长度并且也是切片的初始长度。
3, 切片初始化
s := [] int{1,2,3}
直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3,其cap=len=3
s := arr[:]
初始化切片s,是数组arr的引用
s := arr[starIndex:endIndex]
将arr中从下标startIndex 到 endIndex-1下的元素创建为一个新的切片
s := arr[startIndex:]
s := arr[:endIndex]
s1 := s[startIndex:endIndex]
通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片
4, len() 和 cap() 函数
切片是可索引的,并且可以由len() 方法获取长度。
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
slice01.go
package main
import "fmt"
func main() {
var numbers = make([]int,3,7)
printSlice(numbers)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
5, 空(nil)切片
一个切片在未初始化之前默认为nil,长度为0
slice02.go
package main
import "fmt"
func main() {
var numbers []int
printSlice(numbers)
if(numbers == nil){
fmt.Printf("切片是空的")
}
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
6, 切片截取
可以通过设置下限及上限来设置截取切片 [lower-bound:upper-bound]
slice03.go
package main
import "fmt"
func main() {
numbers :=[]int{0,1,2,3,4,5,6,7,8}
printSlice(numbers)
/* 打印原始切片 */
fmt.Println("numbers == ", numbers)
/* 打印子切片从索引1(包含)到索引4(不包含) */
fmt.Println("numbers[1:4] == ",numbers[1:4])
/* 默认下限为 0 */
fmt.Println("numbers[:3] == ", numbers[:3])
/* 默认上限为len(s) */
fmt.Println("numbers[4:] == ",numbers[4:])
numbers1 := make([]int,0,5)
printSlice(numbers1)
numbers2 := numbers[:2]
printSlice(numbers2)
numbers3 := numbers[2:5]
printSlice(numbers3)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
7, append() 和 copy() 函数
如果想增加切片的容量,我们必须创建一个新的更大的切片把原分片的内容都拷贝过来。
下面的代码描述了从拷贝切片的copy方法到向切片追加新元素的append方法。
slice04.go
package main
import "fmt"
func main() {
var numbers []int
printSlice(numbers)
/* 允许追加空切片 */
numbers = append(numbers,0)
printSlice(numbers)
/* 向切片添加一个元素 */
numbers = append(numbers,1)
printSlice(numbers)
/* 同时添加多个元素 */
numbers = append(numbers,2,3,4)
printSlice(numbers)
/* 创建切片 numbers1 是之前切片的两倍容量 */
numbers1 := make([]int,len(numbers),(cap(numbers))*2)
/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
8, 补充:容量
切片拥有长度和容量
切片的长度是它所包含的元素个数
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。
切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取。
云计算之go语言——基础语法(中)
最新推荐文章于 2025-01-25 10:51:15 发布
本文详细介绍了Go语言中的循环语句,包括for循环、foreach range循环、循环嵌套和循环控制语句,以及条件语句如if、if...else、switch、TypeSwitch和select的使用方法。
1112

被折叠的 条评论
为什么被折叠?



