【GO基础】GO基础语法一

发布于:2024-05-18 ⋅ 阅读:(161) ⋅ 点赞:(0)

一、编写第一个Go程序

1、基本程序结构

package main //包,表名代码所在的模块(包)

import "fmt" //引入代码依赖

//功能实现
func main(){
    fmt.Println("Hello,World!")

}

2、应用程序入口

  1. 必须是main包 package main
  2. 必须是main方法 func main()
  3. 文件名不一定是main.go

3、退出返回值

与其他主要变成语言的差异

  • Go中的main函数不支持任何返回值

1702965849851.png

  • 通过os.Exit 来返回状态

1702965923247.png

4、获取命令行参数

与其他主要变成语言的差异

  • main函数不支持传入参数

    func main~~(arg []string)~~
    
  • 在程序中直接通过os.Args获取命令行参数

二、变量,常量以及与其他语言的差异

1、编写测试程序

  1. 源文件以_test结尾:xxx_test.go
  2. 测试方法以Test开头:func TestXXX(t *testing.T){}
package test

import (
    "log"
    "testing"
)

func TestFirstTry(T *testing.T){

    log.Print("My first try!")
}

1702973622467.png

2、实现Fibonacci数列

1,1,2,3,5,8,13,…

package fib

import (
	"testing"
)

// TestFibList 是测试斐波那契数列生成函数的单元测试函数
func TestFibList(t *testing.T) {
	var a int = 1
	var b int = 1

	// 另一种变量声明方式:
	// var (
	//     a int = 1
	//     b     = 1
	// )

	// 或者使用短变量声明方式:
	// a := 1
	// b := 1

	// 输出变量 a 的值
	t.Log(a)

	// 循环生成斐波那契数列的前5个数并输出
	for i := 0; i < 5; i++ {
		// 输出变量 b 的值
		t.Log(b)

		// 交换 a 和 b 的值,生成下一个斐波那契数
		tmp := a
		a = b
		b = tmp + a
	}
}

1702974208052.png

3、变量赋值

与其他主要变成语言的差异

  • 赋值可以进行自动类型推断
  • 在一个赋值语句中可以对多个变量进行同时赋值
package fib

import (
	"testing"
)

// TestExChange 是测试变量交换函数的单元测试函数
func TestExChange(t *testing.T) {
	// 初始化两个变量 a 和 b 的值
	a := 1
	b := 2

    //temp :=a  
	//a=b
	//b=temp

	// 使用短变量声明方式,同时交换 a 和 b 的值
	// 在 Go 中,可以通过这种方式轻松地实现两个变量的值交换
	a, b = b, a

	// 输出交换后的变量值
	t.Log(a, b)
}

输出结果:
1702974586987.png

4、常量定义

与其他主要变成语言的差异
快速设置连续值
iota枚举
Go里面有一个关键字iota,这个关键字用来声明enum的时候采用,它默认开始值是0,const中每增加一行加1:

package constan_test

import "testing"

// 第一个常量组,使用 iota 枚举星期几
const (
	Monday    = iota + 1
	Tuesday
	Wednesday
)

// 第二个常量组,使用 iota 创建一组表示文件权限的常量
const (
	Readable  = 1 << iota // 位运算左移,表示可读
	Writable              // 位运算左移,表示可写
	Executable            // 位运算左移,表示可执行
)

// TestConstanTry 是测试星期几常量的单元测试函数
func TestConstanTry(t *testing.T) {
	// 输出星期几的常量值
	t.Log("星期一:", Monday)
	t.Log("星期二:", Tuesday)
	t.Log("星期三:", Wednesday)
}

// TestConstanTry1 是测试文件权限常量的单元测试函数
func TestConstanTry1(t *testing.T) {
	//a:=7 // 二进制表示为 0111 TRUE TRUE  TRUE 
	a := 1 // 二进制表示为 0001 true false false

	// 使用位运算检查文件权限
	t.Log("可读:", a&Readable == Readable) 
	t.Log("可写:", a&Writable == Writable)
	t.Log("可执行:", a&Executable == Executable)
}

三、数据类型

数据类型 描述 示例
int 有符号整数类型,大小取决于计算机架构,常用于表示整数。 var x int = 10
int8 有符号8位整数类型,范围为-128到127。 var x int8 = 127
int16 有符号16位整数类型,范围为-32768到32767。 var x int16 = -300
int32 有符号32位整数类型,范围为-2147483648到2147483647。 var x int32 = 100000
int64 有符号64位整数类型,范围为-9223372036854775808到9223372036854775807。 var x int64 = -9223372036854775808
uint 无符号整数类型,大小取决于计算机架构,常用于表示正整数。 var x uint = 10
uint8 无符号8位整数类型,范围为0到255。 var x uint8 = 255
uint16 无符号16位整数类型,范围为0到65535。 var x uint16 = 65535
uint32 无符号32位整数类型,范围为0到4294967295。 var x uint32 = 4294967295
uint64 无符号64位整数类型,范围为0到18446744073709551615。 var x uint64 = 18446744073709551615
float32 32位浮点数类型,可表示小数。 var x float32 = 3.14
float64 64位浮点数类型,可表示小数。 var x float64 = 3.14
complex64 由两个32位浮点数表示的复数类型。 var x complex64 = 3 + 4i
complex128 由两个64位浮点数表示的复数类型。 var x complex128 = 3 + 4i
byte uint8 的别名,常用于表示ASCII字符。 var x byte = ‘A’
rune int32 的别名,常用于表示Unicode字符。 var x rune = ‘你’
string 字符串类型,表示一串字符。 var x string = “Hello”
bool 布尔类型,表示真或假。 var x bool = true
array 数组类型,固定大小的元素序列。 var x [3]int = [3]int{1, 2, 3}
slice 切片类型,可变大小的元素序列。 var x []int = []int{1, 2, 3}
map 映射类型,存储键值对的无序集合。 var x map[string]int = map[string]int{“a”: 1, “b”: 2}
struct 结构体类型,自定义的复合数据类型。 type Person struct {Name string; Age int}

1、类型转化

与其他主要变成语言的差异

  1. Go语言不允许隐式类型转换
  2. 别名和原有类型也不能进行隐式类型转换

1702977014423.png

2、类型的预定义值

math 包提供了一些常用类型的预定义值,包括整数、浮点数等。以下是三个例子:

  1. math.MaxInt64
  2. math.MaxFloat64
  3. math.MaxUint32

package math_constants

import (
    "fmt"
    "math"
)

func ExampleMaxInt64() {
    // 输出 int64 类型的最大值
    fmt.Printf("int64 类型的最大值:%d\n", math.MaxInt64)
}
func ExampleMaxFloat64() {
	// 输出 float64 类型的最大值
	fmt.Printf("float64 类型的最大值:%f\n", math.MaxFloat64)
}
func ExampleMaxUint32() {
	// 输出 uint32 类型的最大值
	fmt.Printf("uint32 类型的最大值:%d\n", math.MaxUint32)
}

func main() {
    ExampleMaxInt64()
    ExampleMaxFloat64()
    ExampleMaxUint32()
}

这些预定义值对于处理数值边界和范围非常有用。

3、指针类型

与其他主要变成语言的差异

  1. 不支持指针运算

在 Go 语言中,指针的使用受到一些限制,其中最明显的一点是不支持指针运算。以下是一个简单的例子,说明了指针运算在 Go 中是不允许的:

package pointer_test

import "testing"

// TestPointerArithmetic 是测试指针运算的单元测试函数
func TestPointerArithmetic(t *testing.T) {
	// 定义一个整数变量 x,并赋值为 10
	x := 10

	// 定义一个指向整数的指针变量 p,指向 x 的内存地址
	p := &x

	// 尝试进行指针运算(不允许的操作),这将导致编译错误
	// p = p + 1  // 这行代码会导致编译错误

	// 输出 x 的值和指针变量 p 的值
	t.Logf("x 的值:%d,指针变量 p 的值:%p", x, p)
}

在这个例子中,尝试进行指针运算 p = p + 1 会导致编译错误,因为在 Go 中不允许直接对指针进行加法或减法运算。

  1. string是值类型,其默认的初始化值为空字符串,而不是null

在 Go 中,string 是一种特殊的值类型,它代表不可变的字符序列。string 的默认初始化值是空字符串而不是 null。以下是一个示例:

package string_test

import "testing"

// TestStringInitialization 是测试 string 初始化的单元测试函数
func TestStringInitialization(t *testing.T) {
    // 声明一个字符串变量 s,其默认初始化值为空字符串
    var s string

    // 输出字符串变量 s 的值
    t.Logf("字符串变量 s 的值:%q", s)
}

在这个例子中,s 是一个字符串变量,由于没有显式赋值,它的默认初始化值是空字符串。通过 %q 格式化符输出字符串时,如果字符串为空,会显示为空字符串而不是 null

四、运算符

1、算数运算符

运算符 描述 示例
+ 加法 a + b
- 减法 a - b
* 乘法 a * b
/ 除法 a / b
% 求余 a % b
++ 自增 a++++a
自减 a––a

Go语言没有前置的++,–(++a)

以下是一个使用算术运算符的简单示例:

package arithmetic_operators

import "fmt"

func main() {
	// 定义两个整数变量
	a := 10
	b := 5

	// 加法
	sum := a + b
	fmt.Printf("加法结果:%d\n", sum)

	// 减法
	difference := a - b
	fmt.Printf("减法结果:%d\n", difference)

	// 乘法
	product := a * b
	fmt.Printf("乘法结果:%d\n", product)

	// 除法
	quotient := a / b
	fmt.Printf("除法结果:%d\n", quotient)

	// 求余
	remainder := a % b
	fmt.Printf("求余结果:%d\n", remainder)

	// 自增
	a++
	fmt.Printf("自增后的值:%d\n", a)

	// 自减
	b--
	fmt.Printf("自减后的值:%d\n", b)
}

2、比较运算符

运算符 描述 示例
== 相等 a == b
!= 不相等 a != b
< 小于 a < b
> 大于 a > b
<= 小于等于 a <= b
>= 大于等于 a >= b
package comparison_operators

import "fmt"

func main() {
	// 定义两个整数变量
	a := 10
	b := 5

	// 相等
	equal := a == b
	fmt.Printf("相等:%t\n", equal)

	// 不相等
	notEqual := a != b
	fmt.Printf("不相等:%t\n", notEqual)

	// 小于
	lessThan := a < b
	fmt.Printf("小于:%t\n", lessThan)

	// 大于
	greaterThan := a > b
	fmt.Printf("大于:%t\n", greaterThan)

	// 小于等于
	lessThanOrEqual := a <= b
	fmt.Printf("小于等于:%t\n", lessThanOrEqual)

	// 大于等于
	greaterThanOrEqual := a >= b
	fmt.Printf("大于等于:%t\n", greaterThanOrEqual)
}

3、用==比较数组

  • 数组的维数必须相同。
  • 数组中元素的个数必须相同。
  • 数组中的每个元素都必须相等。
package test

import (
	"fmt"
	"testing"
)

func TestArrayComparison(t *testing.T) {
	// 定义两个数组
	array1 := [3]int{1, 2, 3}
	array2 := [3]int{1, 2, 3}
	array3 := [3]int{4, 5, 6}

	// 使用 == 比较数组
	equal1 := array1 == array2
	equal2 := array1 == array3

	// 输出比较结果
	fmt.Printf("array1 是否等于 array2:%t\n", equal1)
	fmt.Printf("array1 是否等于 array3:%t\n", equal2)
}


4、逻辑运算符

运算符 描述 示例
&& 逻辑与 a && b
|| 逻辑或 a || b
! 逻辑非 !a
func TestLogical(t *testing.T) {
	// 定义两个布尔变量
	isTrue := true
	isFalse := false

	// 逻辑与
	andResult := isTrue && isFalse
	fmt.Printf("逻辑与结果:%t\n", andResult)

	// 逻辑或
	orResult := isTrue || isFalse
	fmt.Printf("逻辑或结果:%t\n", orResult)

	// 逻辑非
	notResult := !isTrue
	fmt.Printf("逻辑非结果:%t\n", notResult)
}

5、位运算符

运算符 描述 示例
& 位与 a & b
| 位或 a | b
^ 位异或 a ^ b
<< 左移 a << b
>> 右移 a >> b
&^ 位清空 (AND NOT) a &^ b
func TestBitwiseOperators(t *testing.T) {
    // 定义两个整数变量
    a := 5    // 二进制: 0101
    b := 3    // 二进制: 0011

    // 位与
    andResult := a & b
    fmt.Printf("位与结果:%d\n", andResult) // 0001 (1)

    // 位或
    orResult := a | b
    fmt.Printf("位或结果:%d\n", orResult) // 0111 (7)

    // 位异或
    xorResult := a ^ b
    fmt.Printf("位异或结果:%d\n", xorResult) // 0110 (6)

    // 左移
    leftShiftResult := a << 1
    fmt.Printf("左移结果:%d\n", leftShiftResult) // 1010 (10)

    // 右移
    rightShiftResult := a >> 1
    fmt.Printf("右移结果:%d\n", rightShiftResult) // 0010 (2)

    // 位清空 (AND NOT)
    clearResult := a &^ b
    fmt.Printf("位清空结果:%d\n", clearResult) // 0100 (4)
}

与其他主要变成语言的差异

  • ** **&^按位置零

该操作符的使用方式是 a &^ b,它的作用是将 b 中为 1 的位在 a 中对应位置上清零。

func TestBitwiseClear(t *testing.T) {
	// 定义两个整数变量
	a := 5    // 二进制: 0101
	b := 3    // 二进制: 0011

	// 使用 &^ 按位清零
	result := a &^ b

	// 输出结果
	fmt.Printf("a &^ b 按位清零结果:%d\n", result) // 0100 (4)
}

五、循环

与其他主要变成语言的差异
GO语言仅支持循环关键字for

1. 基本的 for 循环:

	// 基本的 for 循环
	for i := 1; i <= 5; i++ {
		fmt.Println(i)
	}

2. for range 循环:

func TestFor(t *testing.T) {
	// 使用 for range 遍历数组
	numbers := []int{1, 2, 3, 4, 5}
	for index, value := range numbers {
		fmt.Printf("索引:%d,值:%d\n", index, value)
	}

	// 使用 for range 遍历字符串
	message := "Hello, Go!"
	for index, char := range message {
		fmt.Printf("索引:%d,字符:%c\n", index, char)
	}
}

3. while 条件循环:

func TestFor01(t *testing.T) {
	// 模拟 while 循环
	counter := 1
	for counter <= 5 {
		fmt.Println(counter)
		counter++
	}
}

4. 无限循环:

func TestFor02(t *testing.T) {
    // 无限循环
    counter := 0
    for {
        fmt.Println("无限循环")
        counter++

        if counter == 3 {
            break // 终止循环
        }
    }
}

5.if条件

1. 基本的 if 语句:
// 基本的 if 语句
x := 10

if x > 5 {
    fmt.Println("x 大于 5")
} else {
    fmt.Println("x 不大于 5")
}
2. if 语句的条件可以包含初始化语句:
// if 语句的条件包含初始化语句
	if x := 10; x > 5 {
		fmt.Println("x 大于 5")
	} else {
		fmt.Println("x 不大于 5")
	}
  

在这个例子中,if 语句的条件部分包含了初始化语句 x := 10,这个变量 x 只在 if 语句的作用域内有效。

3.多个 if 语句的嵌套
	// 多个 if 语句的嵌套
	x := 10

	if x > 5 {
		fmt.Println("x 大于 5")

		if x > 8 {
			fmt.Println("x 大于 8")
		}
	} else {
		fmt.Println("x 不大于 5")
	}

与其他主要变成语言的差异

  1. condition 表达式结果必须为布尔值

在 Go 语言中,条件表达式的结果必须是一个布尔值。这意味着 iffor 等语句中的条件表达式必须评估为布尔类型,不能接受非布尔类型的值

// Go 语言中的条件表达式必须是布尔值
if x > 5 {
    // ...
}

// 错误示例,编译时将会报错
if x {
    // ...
}

在上述错误示例中,x 是一个变量,但它的类型不是布尔类型,因此这个条件表达式会导致编译错误。相比之下,一些其他语言可能允许使用非布尔类型的值作为条件。

  1. 支持变量赋值

6.switch条件

与其他主要变成语言的差异
1.条件表达式不限制为常量或者整数;

func TestSwitch(t *testing.T) {
	var x interface{} = "hello"

	switch x.(type) {
	case int:
		fmt.Println("x 是一个整数")
	case string:
		fmt.Println("x 是一个字符串")
	default:
		fmt.Println("未知类型")
	}

}

switch 语句的条件表达式可以是任意类型,不限制为常量或整数。这使得 switch 可以用于更复杂的条件判断,例如字符串、接口等类型。

2.单个 case 中,可以出现多个结果选项,使用逗号分隔;

func TestSwitch2(t *testing.T) {
	num := 2

	switch num {
	case 1, 2:
		fmt.Println("数字是1或2")
	case 3:
		fmt.Println("数字是3")
	default:
		fmt.Println("未知数字")
	}

}

3.与C语言等规则相反,Go 语言不需要用break来明确退出一个 case;

func TestSwitch3(t *testing.T) {
	day := "Monday"
	switch day {
	case "Monday":
		fmt.Println("星期一")
	case "Tuesday":
		fmt.Println("星期二")
	default:
		fmt.Println("其他日子")
	}
}

4.可以不设定switch 之后的条件表达式,在此种情况下,整个 switch 结构与多个 if…else…的逻辑作用等同

func TestSwitch4(t *testing.T) {
	num := 2

	switch {
	case num > 5:
		fmt.Println("数字大于5")
	case num > 0:
		fmt.Println("数字大于0")
	default:
		fmt.Println("未知数字")
	}
}


网站公告

今日签到

点亮在社区的每一天
去签到