每日一Go-3、Go语言基础语法

30 阅读7分钟

Go语言的基础语法分三个方面:变量、数据类型、控制结构

1、变量声明

  • 1.1 标准声明 (var 变量名 变量类型)
//显示指定数据类型
var name string = `Coding君` 
var age int 
//只声明不立即初始化
var title string
//批量声明变量
var (  
    hobby string   
    score int  
    online bool
)
  • 1.2 短变量声明 (:=)
//自动推断为string类型
name := `Coding君` 
//自动推断为int类型
age := 18 
//多返回值
val,err := getOne() 

2、基本数据类型基本数据类型分为布尔型、数值型(整型|浮点型|复数型)、字符串型和派生类型(数组|切片|映射|结构体|指针)

//布尔型
var online bool 
//数值型
//整型
var age int
var age int8
var age uint //无符号整型
//浮点型
var score float32 
var score float64
//复数型
var complx complex64 
var complx complex128
//字符串型
var name string
//派生类型 数组、切片、映射、结构体、指针
//数组
var hobbies [3]string //长度固定
hobbies[0] = "reading"
hobbies[1] = "coding"
hobbies[2] = "gaming"
fmt.Println("My hobbies are:", hobbies) 
//切片,这是用的最多的
bodys := []string{} //长度不固定
bodys = append(bodys, "head", "shoulders", "knees", "toes")
fmt.Println("Body parts:", bodys)
//映射
bodyFunctions := map[string]string{}
bodyFunctions["head"] = "thinking"
bodyFunctions["shoulders"] = "carrying"
bodyFunctions["knees"] = "bending"
bodyFunctions["toes"] = "balancing"
fmt.Println("Body functions:", bodyFunctions)
//结构体 struct
type Person struct{
  name string
  age int
}
//指针
var xiaoming *Person
xiaoming = &Person{name: `小明`, age: 20}
fmt.Println("Name:", xiaoming.name, "Age:", xiaoming.age)
//推荐用法
xiaohong := &Person{name: `小红`, age: 18}
fmt.Println("Name:", xiaohong.name, "Age:", xiaohong.age)

打开go的源文件src/builtin/builtin.go查看类型的定义,如下:

package builtin

import "cmp"

// bool is the set of boolean values, true and false.
type bool bool

// true and false are the two untyped boolean values.
const (
true  = 0 == 0 // Untyped bool.
false = 0 != 0 // Untyped bool.
)

// uint8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type uint8 uint8

// uint16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type uint16 uint16

// uint32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type uint32 uint32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// int8 is the set of all signed 8-bit integers.
// Range: -128 through 127.
type int8 int8

// int16 is the set of all signed 16-bit integers.
// Range: -32768 through 32767.
type int16 int16

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type int64 int64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// complex64 is the set of all complex numbers with float32 real and
// imaginary parts.
type complex64 complex64

// complex128 is the set of all complex numbers with float64 real and
// imaginary parts.
type complex128 complex128

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// uint is an unsigned integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, uint32.
type uint uint

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32

// any is an alias for interface{} and is equivalent to interface{} in all ways.
type any = interface{}

// comparable is an interface that is implemented by all comparable types
// (booleans, numbers, strings, pointers, channels, arrays of comparable types,
// structs whose fields are all comparable types).
// The comparable interface may only be used as a type parameter constraint,
// not as the type of a variable.
type comparable interface{ comparable }

// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int

// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1 int

// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
type IntegerType int

// FloatType is here for the purposes of documentation only. It is a stand-in
// for either float type: float32 or float64.
type FloatType float32

// ComplexType is here for the purposes of documentation only. It is a
// stand-in for either complex type: complex64 or complex128.
type ComplexType complex64

关于类型的转换,Go要求显示转换,不支持隐式转换

var x int32 = 100
y := int64(x) // 必须显式转换
f := 3.14
i := int(f) // 浮点转整型会截断小数部分,i 的值为 3
fmt.Println("f:", f, "i:", i)
//打印结果:f: 3.14 i: 3
//但是,在实际中,我们使用cast包(github.com/spf13/cast)来转换数据
yy := cast.ToInt64(x) 
fmt.Println("yy:", yy)
ii:= cast.ToInt(f)
fmt.Println("ii:", ii)

3、控制结构

  • 3.1 条件语句(if/else)Go的if语句条件不需要小括号()包裹
// 常见的写法:在条件前初始化
if score := 85; score >= 90 { // 此处的 score 只在 if 和 else 块中有效
    fmt.Println("优秀")
} else if score >= 60 {
    fmt.Println("及格")
} else {
    fmt.Println("不及格")
}
  • 3.2 循环(for)Go中只有for一种循环关键字,没有while、do-white等其他循环
//标准循环
for i := 0; i < 5; i++ {
  fmt.Println(i)
}
//类似 while 循环
for count:=0;count<10; {
  fmt.Println("count:",count)
  count++
}
//无限循环
for {
  break // 立即退出循环
}
//遍历数组、切片、映射等集合类型时,使用 for range循环非常方便
//遍历数组
var arr = [3]string{"apple", "banana", "cherry"}
for index, fruit := range arr {
  fmt.Printf("索引: %d, 水果: %s\n", index, fruit)
}
//遍历切片
for index, part := range bodys {
  fmt.Printf("索引: %d, 部位: %s\n", index, part)
}
//遍历映射
for key, value := range bodyFunctions {
  fmt.Printf("部位: %s, 功能: %s\n", key, value)
}
  • 3.3 多路分支(switch)在 Go 中,每个 case默认会自动跳出,无需写 break
 weather := "晴天"
    switch weather {
    case "晴天":
        fmt.Println("适合出去玩")
    case "下雨":
        fmt.Println("记得带伞")
    case "下雪":
        fmt.Println("注意保暖")
    default:
        fmt.Println("天气情况未知")
    }
    //把weather放在case里去判断
    switch {
    case weather == "晴天":
        fmt.Println("适合出去玩")
    case weather == "下雨":
        fmt.Println("记得带伞")
    case weather == "下雪":
        fmt.Println("注意保暖")
    default:
        fmt.Println("天气情况未知")
    }
    //使用fallthrough实现穿透效果
    //即无论匹配到哪个case,都会继续执行后续的case语句
    //相当于去掉了默认的break
    switch weather {
    case "晴天":
        fmt.Println("适合出去玩")
        fallthrough
    case "下雨":
        fmt.Println("记得带伞")
        fallthrough
    case "下雪":
        fmt.Println("注意保暖")
    default:
        fmt.Println("天气情况未知")
    }

4、实践环节我们来做一个计算器吧

var num1, num2 float64
    var operator string
    // 获取用户输入
    fmt.Print("请输入第一个数字: ")
    _, err := fmt.Scanln(&num1)
    if err != nil {
        fmt.Println("输入错误,请输入数字")
        return
    }
    fmt.Print("请输入第二个数字: ")
    _, err = fmt.Scanln(&num2)
    if err != nil {
        fmt.Println("输入错误,请输入数字")
        return
    }
    fmt.Print("请输入运算符 (+, -, *, /): ")
    fmt.Scanln(&operator)
    // 根据运算符进行计算
    switch operator {
    case "+":
        fmt.Printf("%.2f + %.2f = %.2f\n", num1, num2, num1+num2)
    case "-":
        fmt.Printf("%.2f - %.2f = %.2f\n", num1, num2, num1-num2)
    case "*":
        fmt.Printf("%.2f * %.2f = %.2f\n", num1, num2, num1*num2)
    case "/":
        if num2 != 0 {
            fmt.Printf("%.2f / %.2f = %.2f\n", num1, num2, num1/num2)
        } else {
            fmt.Println("错误:除数不能为零")
        }
    default:
        fmt.Println("错误:未知的运算符")
    }
    //运行结果如下:
    //请输入第一个数字: 1
    //请输入第二个数字: 2
    //请输入运算符 (+, -, *, /): +
    //1.00 + 2.00 = 3.00

万丈高楼平地起,不积跬步无以至千里,坚持下去,终将美好