go语言基础上

45 阅读6分钟

1.数据的输入和输出

1.1数据的输入

 var num1, num2 int
    fmt.Print("请输入两个整数,用空格分隔: ")
    _, err := fmt.Scanln(&num1, &num2)

这里面的输入结果和c++和java有点不太一样 _指的是不在意读取的数据的个数,err指的是是否发生了错误

1.2 数据的输出

k:="apple"
    fmt.Println(k)

2.变量的声明和赋值

有两种方式声明变量

var a = "initial"
 k:="apple"

go语言的变量声明也和c++和java有些许不同,变量声明出来必须使用,如果不使用编辑器就会报错,无法编译

声明一个字符串变量但先不赋值

// 声明一个字符串变量
    var str string

    // 给字符串变量赋值
    str = "Hello, World!"
    // 声明一个字符变量
    var ch rune

    // 给字符变量赋值
    ch = 'A'

3.for循环

go语言里面没有while循环,只有for循环 for循环示例

for j := 7; j < 9; j++ {
		fmt.Println(j)
	}
 for i <= 3 {
		fmt.Println(i)
		i = i + 1
	}

和java和c++不太一样的地方在go语言里面for循环不需要括号,也不需要一定要写两个;,相当于用一个for通过充当了while和for的作用

4.if语句

示例

if 7%2 == 0 {
		fmt.Println("7 is even")
	} else {
		fmt.Println("7 is odd")
	}
if num := 9; num < 0 {
		fmt.Println(num, "is negative")
	} else if num < 10 {
		fmt.Println(num, "has 1 digit")
	} else {
		fmt.Println(num, "has multiple digits")
	}

和c++和java一样,但是不用写括号了,还可以在if条件里面写变量的声明

5. switch语句

a := 2
	switch a {
	case 1:
		fmt.Println("one")
	case 2:
		fmt.Println("two")
	case 3:
		fmt.Println("three")
	case 4, 5:
		fmt.Println("four or five")
	default:
		fmt.Println("other")
	}

不需要在每一个case后面写break了,因为只会执行一次,而且switch里面的判断条件也更加丰富

6.数组

一维数组

//声明但是不赋值
var a [5]int
	a[4] = 100
 //声明且赋值
 k:=[5]int{1,2,3,4,5}
	fmt.Println(len(k))

二维数组

var twoD [2][3]int
	for i := 0; i < 2; i++ {
		for j := 0; j < 3; j++ {
			twoD[i][j] = i + j
		}
	}
 b:=[2][3]int{{1,2,3},{4,5,6}}

7.字符串

声明

s := make([]string, 3)
	s[0] = "a"
	s[1] = "b"
	s[2] = "c"
  //声明字符串数组 声明时不赋值
  var a [4]string
	a[0] = "a"
  //声明字符串数组同时赋值
  good := []string{"g", "o", "o", "d"}

库函数

  1. strings.Contains: 检查一个字符串是否包含另一个字符串。
  2. strings.Count: 计算一个字符串在另一个字符串中出现的次数。
  3. strings.EqualFold: 比较两个字符串是否相等,忽略大小写。
  4. strings.Index: 返回一个字符串在另一个字符串中第一次出现的位置。
  5. strings.Join: 将一个字符串切片连接成一个字符串。
  6. strings.Repeat: 重复一个字符串指定的次数。
  7. strings.Replace: 替换一个字符串中的所有指定子串。
  8. strings.Split: 将一个字符串分割成字符串切片。
  9. strings.ToLower: 将一个字符串转换为小写。
  10. strings.ToUpper: 将一个字符串转换为大写。

8.map容器

声明一个map容器

m := make(map[string]int)

声明并对map容器初始化

m2 := map[string]int{"one": 1, "two": 2}

清除map容器的一个键值

delete(m, "one")

遍历map容器

// 使用range遍历map中的所有键值对
    for key, value := range m {
        fmt.Println(key, value)
    }

判断map容器里面的键值是否存在

r, ok := m["unknow"]
	fmt.Println(r, ok) 

r, ok := m["unknow"] : 这是一个赋值语句,它使用了短变量声明和赋值操作符:=。这里发生了两件事:

r被赋值为从映射m中获取的值。如果键"unknow"存在,r将是对应的值;如果不存在,r将是int类型的零值0ok是一个布尔值,用于指示键"unknow"是否存在于映射m中。如果键存在,ok将被设置为true;如果键不存在,ok将被设置为false

map容器里面键值的数量

  fmt.Println(len(m));

9.range

遍历数组和容器

for i, num := range nums {
nums := []int{2, 3, 4}
	sum := 0
		sum += num
		if num == 2 {
			fmt.Println("index:", i, "num:", num) // index: 0 num: 2
		}
	}
        //遍历容器 
        遍历map容器返回的键值对是无序的
        m := map[string]string{"a": "A", "b": "B"}
	for k, v := range m {
		fmt.Println(k, v) // b 8; a A
	} 
        //可以不是k,v,只需要是两个参数就可以

可以只遍历值,只需要用_来忽略键,示例如下 对于数组也同样适用

 m := map[string]string{"a": "A", "b": "B"}
	for _, v := range m {
		fmt.Println( v) //B ; A
	}

如果直接直接用一个变量去接受,就是遍历键 对于数组来说就是遍历值

  m := map[string]string{"a": "A", "b": "B"}
  for v := range m {
		fmt.Println(v) // a;  b
	}
   nums := []int{2, 3, 4}
	sum := 0
	for num := range nums {
		sum += num
		if num == 2 {
			fmt.Println("num:", num) //num: 2
		}
       }

在通道(channel)上使用range

 ch := make(chan int)
go func() {
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch)
}()
for num := range ch {
    fmt.Println(num)
}

10.函数

函数的声明 最重要的就是参数后置

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

和c++和java不同的是,go语言的函数可以返回多个参数 在函数体里面,可以直接写return即可

func exists(m map[string]string, k string) (v string, ok bool) {
	v, ok = m[k]
	return 
}

函数也可以接受可变参数,使用...符号

func sum(nums...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

匿名函数 可以在需要的地方使用匿名函数,不需要写函数的名字

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

可以处理异常

Go语言中通常通过返回一个额外的错误类型参数来处理错误

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
    //在go里面nil就是null的意思指没有错误
}

可以实现延迟调用 通过defer来实现在函数返回之前执行一些清理操作

func readFile(filename string) (string, error) {
    file, err := os.Open(filename)
    if err!= nil {
        return "", err
    }
    defer file.Close() // 确保在函数返回前关闭文件

    // 读取文件内容
    //...

    return "文件内容", nil
}

闭包函数

示例

func createCounter() func() int {
  x := 0
   return func() int {
     x++
     return x
   } 
}
func main() {
    increment := createCounter()
    fmt.Println(createCounter()) // 输出: 1
    fmt.Println(createCounter()) // 输出: 2
    fmt.Println(createCounter()) // 输出: 3
}

解释

  1. createCounter 函数

    • createCounter 函数没有参数,它的目的是创建一个计数器。
    • 在函数内部,声明了一个局部变量 x,并初始化为 0
    • 函数返回一个匿名函数,这个匿名函数没有参数,返回一个 int 类型的值。
  2. 匿名函数(闭包)

    • 匿名函数内部的 x 变量是对外部函数 createCounter 中 x 变量的引用。
    • 每次调用这个匿名函数时,它会将 x 的值加 1,然后返回新的值。
    • 由于 x 是外部函数的局部变量,它的生命周期会随着闭包的存在而延长,即使外部函数 createCounter 已经返回。
  3. 使用闭包

    • 在 main 函数中,调用 createCounter 函数会返回一个计数器函数。
    • 将这个计数器函数赋值给变量 increment
    • 每次调用 increment 函数时,它会返回一个比上次调用时更大的整数。