其他分享
首页 > 其他分享> > 第二章 Go基础语法

第二章 Go基础语法

作者:互联网

第二章 Go基础语法

2.1 变量定义

创建变量方式(定义变量可不赋初值也可赋初值):

  1. 不赋初值
  1. 赋初值

Go语言很严格,只要是定义了的变量一定要用到,不然会报错

  1. 创建变量时省略变量类型

Go语言可以省略变量类型直接赋值,编译器会自动识别变量的类型,如:

  1. 更短的创建变量的方法
  1. 关于函数外面的变量声明

Go语言没有全局变量的说法,函数外面的变量是包内部的变量,作用域仅限于包内部

package main

import "fmt"

//在函数外面也可以定义变量,但不可以用:来定义变量
//函数外面的语句开头必须有var或者func
var aa = 2
var ss = "kk"
//bb := true//函数外面不可用:来定义变量

var (
	cc = 4
	gg = true
	hh = "anc"
)//还可以用括号的形式一次性定义多个变量,避免重复写var

func variableZeroValue() {
   var a int
   var s string
   fmt.Println(a, s)//0
   fmt.Printf("%d %q \n", a, s)//0 “”
}

func variableInitialValue() {
	var a int = 3
	//var b, c int = 1, 2//Go语言很严格,只要是定义了的变量一定要用到,不然会报错
	var s string = "abc"
	fmt.Println(a, s) //3 abc
}

func variableTypeDeduction() {
	var a, b, c, d = 3, 4, true, "abc"
	fmt.Println(a, b, c, d)//3 4 true abc
}

func variableShorter() {
	a, b, c, d := 3, 4, true, "abc" //将var去掉,在=前面加:,这样跟var a, b, c, d = 3, 4, true, "abc"是一样的
	b = 5                           //第二次赋值变量就不能加:了,就像已经var过的变量第二次赋值就不加var一样
	fmt.Println(a, b, c, d)         //3 5 true abc
}

func main() {
	fmt.Println("hello world")
	variableZeroValue()
	variableInitialValue()
	variableTypeDeduction()
    variableShorter()
}

【注】关于fmt.Println()

package main

import "fmt"

func main() {
   a, b, c, d, e := 1, 2, 3, 4, 5
   fmt.Println(
      a,
      b,
      c,
      d,
      e,
   )//可以通过逗号来输出多个值,若Println的右括号跟e在同一行,则e后不用加逗号
}

2.2 内建变量类型

2.2.1 变量类型

2.2.2 强制类型转换

Go语言中类型转换是强制的

举例:利用math.Sqrt()计算平方根

package main

import (
   "fmt"
   "math"
)

func main() {
   var a, b int = 3, 4
   var c int = int(math.Sqrt(float64(a*a + b*b)))
   fmt.Println(c)//5
}

2.3 常量与枚举

2.3.1 常量

Go语言中的常量不像其他语言在定义的时候要大写

  1. 常量的关键词是const,可以在变量后声明变量的类型,也可以不声明,如:const filename = "abc.txt"const a,b = 3,4const filename string = "abc.txt"const a,b int = 3,4

  2. 当不对常量进行类型的声明时,如const a,b = 3,4,此时的a、b既可以为int型也可以为float,即const数值可以作为各种类型使用,于是再调用math.Sqrt()计算以a、b为直角边的三角形的斜边长度时,就无需强制转换了,如下:

package main

import (
   "fmt"
   "math"
)

func main() {
   const a, b = 3, 4
   var c int = int(math.Sqrt(a*a + b*b))
   fmt.Println(c)//5
}
  1. 常量也可以在函数外定义作为包内都可以使用的常量
  2. 常量可以用括号的形式一次性定义多个常量,如下:
package main

import (
   "fmt"
   "math"
)

const (
   a, b     = 3, 4
   filename = "abc.txt"
)

func main() {
   var c int = int(math.Sqrt(a*a + b*b))
   fmt.Println(c)//5
   fmt.Println(filename)//abc.txt
}

2.3.2 使用常量定义枚举类型

Go语言没有特殊的枚举关键字,一般是用一组const来定义枚举类型

package main

import "fmt"

func enums1() {
   const (
      a = 0
      b = 1
      c = 2
      d = 3
      e = 4
   )
   fmt.Println(a, b, c, d, e)
}

func enums2() {
   const (
      cpp = iota
      java
      python
      golang
   )
   fmt.Println(cpp, java, python, golang)
}

func enums3() {
   const (
      aa = iota
      _
      cc
      dd
      ee
   )
   fmt.Println(aa, ee, cc, dd)
}

func enums4() {
   const (
      b = 1 << (10 * iota)
      kb
      mb
      gb
      tb
      pb
   )
   fmt.Println(b, kb, mb, gb, tb, pb)
}

func main() {
   enums1() //0 1 2 3 4
   enums2() //0 1 2 3
   enums3() //0 4 2 3
   enums4() //1 1024 1048576 1073741824 1099511627776 1125899906842624
}

2.4 条件语句

2.4.1 if

本节新内容:

  1. Go语言条件语句格式:
func branch(v int) int {
   if v > 100 {
      return 100
   } else if v < 0 {
      return 0
   } else {
      return v
   }
}
  1. nil关键字相当于别的语言的null
  2. func ReadFile(filename string) ([]byte, error)方法,用于读取文件,返回值有两个,分别是[]byte类型和error类型

以下为读取文件的条件语句流程:若没有abc.txt文件则会报错,需建好此文件才能正确读出

package main

import (
   "fmt"
   "io/ioutil"
)

func main() {
   const filename = "abc.txt"
   contents, err := ioutil.ReadFile(filename)
   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Printf("%s\n", contents)
   }
}

以上的代码可以写成以下的形式:

package main

import (
   "fmt"
   "io/ioutil"
)

func main() {
   const filename = "abc.txt"
    //在if里面赋值:
   if contents, err := ioutil.ReadFile(filename); err != nil {
      fmt.Println(err)
   } else {
      fmt.Printf("%s\n", contents)
   }
    //此时再用fmt.println(contents)是不行的,因为它只存在于if区域中
}

2.4.2 switch

Go语言与其他语言中的switch用法上的区别:

例1:

func calculator(a, b int, op string) int {
   var result int
   switch op {
   case "+":
      result = a + b
   case "-":
      result = a - b
   case "*":
      result = a * b
   case "/":
      result = a / b
   default:
      panic("unsupported operator:" + op)
   }
   return result
}

例2:

package main

import "fmt"

func grade(s int) string {
   var temp string
   switch {
   case s < 0 || s > 100:
      panic(fmt.Sprintf("wrong score:%d", s))
   case s < 60:
      temp = "F"
   case s <= 70:
      temp = "C"
   case s <= 80:
      temp = "B"
   case s <= 100:
      temp = "A"
   }
   return temp
}

func main() {
   fmt.Println(
      grade(10),
      grade(100),
      grade(0),
      grade(70),
   )
}

2.3 循环语句

  1. Go中for的初始条件可以省略

例1:二进制数转换器

package main

import (
   "fmt"
   "strconv"
)

func convertToBin(n int) string {
   //二进制思想:设置一个循环,十进制数n用来跟2来取模,其每一次的结果从左往右依次进栈在result里,再进行n/2操作
   //如11转换成二进制的过程:
   //第一步:11%2 = 1,result = 1,11/2 = 5
   //第二步:5%2 = 1,result = 11,5/2 = 2
   //第三步:2%2 = 0,result = 011,2/2 = 1
   //第四步:1%2 = 1,result = 1011,1/2 = 0
   //所以结果是1011
   result := ""
   if n != 0 {
      for ; n > 0; n /= 2 {
         result = strconv.Itoa(n%2) + result
      }
   } else {
      result = strconv.Itoa(0)
   }
   return result
}

func main() {
   fmt.Println(convertToBin(0)) //0
   fmt.Println(convertToBin(11))//1011
}

2.Go中for的递增条件可以省略

for没有初始条件也没有递增条件,连分号" ; "都能省略

例2:读取文件

package main

import (
   "bufio"
   "fmt"
   "os"
)

func printFile(filename string) {
   file, err := os.Open(filename)
   if err != nil {
      panic(err)
   }

   scanner := bufio.NewScanner(file)

   for scanner.Scan() {
      fmt.Println(scanner.Text())
   }
}

func main() {
   printFile("abc.txt")
}
  1. Go中for后可以没有任何内容,此时是死循环
package main

import "fmt"

func forever() {
   for {
      fmt.Println("abc")
   }
}

func main() {
   forever()//不停地输出“abc”
}

2.4 函数

  1. Go语言中的函数可以返回多个值,并且可以给返回的值起名字

    例1:

package main

import "fmt"

//带余数的除法,可以给返回的值起名字
func div(a, b int) (q, r int) {
   return a / b, a % b
}

//也可以写成这种形式,但仅用于非常简单的函数
func div2(a, b int) (q, r int) {
	q = a / b
	r = a % b
	return
}

func main() {
   fmt.Println(div(11, 2))//5 1
}

例2:

package main

import "fmt"

func calculator(a, b int, op string) (int, error) {
   switch op {
   case "+":
      return a + b, nil
   case "-":
      return a - b, nil
   case "*":
      return a * b, nil
   case "/":
      q, _ := div(a, b) //当返回值有多个,但只想接收一个返回值时,可以用下划线“_”来省略接收的变量
      return q, nil
   default:
      return 0, fmt.Errorf("unsupported operation:%s", op)
   }
}

//带余数的除法
func div(a, b int) (q, r int) {
   return a / b, a % b
}

func main() {
   if result, err := calculator(11, 2, "+"); err != nil {
      fmt.Println("error:", err)
   } else {
      fmt.Println(result)
   }
}
  1. 函数式编程
package main

import (
   "fmt"
   "math"
   "reflect"
   "runtime"
)

//op是传递进去的函数名字,op是一个传入两个int返回一个int的函数,apply是一个传入一个函数和两个int返回一个int的函数
//apply()函数return的是op(a,b)的结果
func apply(op func(int, int) int, a, b int) int {
   p := reflect.ValueOf(op).Pointer()
   opName := runtime.FuncForPC(p).Name() //拿到传入函数的名字
   fmt.Printf("Calling function %s with args "+
      "(%d,%d)\n", opName, a, b) //打印调用的函数名字以及进行运算的两个参数

   return op(a, b)
}

//因为pow()传入的两个参数是float64型,所以对其进行重写,使其传入的两个参数是int型
func pow(a, b int) int {
   return int(math.Pow(float64(a), float64(b)))
}

func main() {
   fmt.Println(apply(pow, 3, 4))
   //在调用一个参数有函数的函数时,可以直接在调用时现场编写一个函数,此函数无需给名字,即匿名函数,如下:
   fmt.Println(apply(
      func(a, b int) int {
         return int(math.Pow(float64(a), float64(b)))
      }, 3, 4))
}
  1. 可变参数列表

Go语言没有默认参数、可选参数、函数重载,只有可变参数列表

package main

import "fmt"

func sum(numbers ...int) int {
   s := 0
   for i := range numbers {
      s += numbers[i]
   }
   return s
}

func main() {
   fmt.Println(sum(1, 2, 3))    //6
   fmt.Println(sum(1, 2, 3, 4)) //10
   fmt.Println(sum(1, 2, 3, 5)) //11
}

2.5 指针

2.5.1 Go语言的指针特点

package main

import "fmt"

func main() {
   var a int = 2
   var pa *int = &a
   *pa = 3
   fmt.Println(a)
}

2.5.2 Go语言的参数传递

Go语言只有值传递一种方式,但Go可以通过指针来实现引用传递的作用

Go语言指针实例:

package main

import "fmt"

func main() {
   var a = 2
   var b = &a
   var c *int = &a
   *c = 3
   fmt.Println(a, *b) //3 3
}

image

go语言的参数传递只能是值传递,所以这里实际上相当于在函数中拷贝了一个a进行操作

image

同理这里是拷贝了a的地址,pa指向a的值,可以通过修改pa指向的值来达到修改数值的目的

image

函数内是拷贝了一份cache结构中指向data的指针pData来达到改变data的目的

下面列举数个交换两变量数值的方法:

package main

import "fmt"

//这样互换值的方法是正确的
func swap1(a, b *int) {
   *a, *b = *b, *a
}

//失败的互换方法
func swap2(a, b *int) {
   *a = *b
   *b = *a
}

//引用第三个值来将两个值互换
func swap3(a, b *int) {
   c := *a
   *a = *b
   *b = c
}

//最好的互换数值的方式
func swap4(a, b int) (int, int) {
   return b, a
}

func main() {
   a, b := 3, 4
   a, b = swap4(a, b)
   fmt.Println(a, b) //4 3
}

标签:Println,main,int,fmt,语法,var,func,Go,第二章
来源: https://www.cnblogs.com/Ayisprite/p/16435370.html