• Go语言基础之基本语法


    基本结构

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("Hello,World!")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    )
    
    func handler(w http.ResponseWriter,r *http.Request)  {
    	s := "你好,世界!"
    	fmt.Fprintf(w,"%s",s)
    	log.Printf("%s",s)
    }
    func main() {
    	fmt.Println("server start.")
    	http.HandleFunc("/",handler)
    	if err := http.ListenAndServe("localhost:1234",nil); err != nil {
    		log.Fatal("ListenAndServe:",err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • Go语言是编译型语言,将这几行代码保存在hello.go文件中,然后在文件当前目录下,命令行执行go run hello.go即可执行该,在命令行会输出Hello,World!,然而实际处理流程仍会先将其编译为二进制机器指令,然后链接相关资源再运行,最后输出结果
    • 实际上可以将编译和执行分为两步,先使用命令go build指令进行编译,然后找到编译生成的二进制文件直接执行该文件即可

    实际执行结果如下所示

    PS D:\book\ch01\1.1\helloworld> go run hello.go
    Hello,World!
    PS D:\book\ch01\1.1\helloworld> go build hello.go
    PS D:\book\ch01\1.1\helloworld> ls
    
    
        目录: D:\book\ch01\1.1\helloworld
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----       2022/12/27     17:08        2108024 hello
    -a----       2022/12/28     16:44        1937408 hello.exe
    -a----       2022/12/27     17:08             80 hello.go
    
    
    PS D:\book\ch01\1.1\helloworld> .\hello.exe
    Hello,World!
    PS D:\book\ch01\1.1\helloworld>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第二段代码的执行

    PS D:\book\ch01\1.1\helloserver> go run .\main.go
    server start.
    2022/12/28 17:16:55 你好,世界!
    2022/12/28 17:16:55 你好,世界!
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    同时打开浏览器,访问地址localhost:1234,也会显示你好,世界!

    结构解析

    package main:包的声明,也是没个项目的入口,main包是独立的可执行程序,包是Go语言项目结构的核心组成部分,如果其他Go程序要导入已有的程序,要通过import将对应的包引入;每一个Go语言程序的第一行都是包的声明,每个包可以有一个或者多个以.go为扩展名的文件

    import:导入了Go语言提供的基础包fmt,Go语言提供了大量的标准包,此外用户自己开发的包也可以通过这种方式导入,在import关键字后使用小括号可以写入用到的多个包;这里需要注意的是与其他语言不同的,使用import导入的包必须在本程序中用到,如果导入了但没有用到,编译是无法通过的,同样的声明的变量也必须用到,否则也无法编译通过

    func:是定义函数和方法的关键字,func关键后跟函数名,小括号内是参数列表,函数体用大括号括起来

    fmt.Println("Hello,World!"):使用fmt的Println函数打印一个字符串,函数名的第一个字母大写表示包外可见,此外语句后面不需要加分号,只有当把多行代码写在一行的时候才会使用分号隔离,但这是非常差的写法,与Java不同与Python类似,但又不同于Python,Go语言在编译的时候会把换行符解析为分号,因此在实际写代码的时候注意换行即可,且函数体的大括号({)如果单独放在一行编译也是无法通过的

    在第二段代码中,使用Go语言构建了一个Web服务,Go语言构建Web服务非常简单,直接使用标准的net/http包即可

    代码中定义了函数handler,其参数是固定的,因为要满足接口的要求,其中第二个参数前面带个*号,表示此处参数的传递是传指针,http.Request代表一次请求,是一个结构体

    :=表示声明和赋值另个动作一并完成,如果仅仅是声明而不赋值,则需要使用关键字var来声明,并且:=必须是未声明的变量,如果声明过则无法使用此方法来赋值

    http.HandleFunc("/",handler)讲路径和处理函数绑定,表明请求该路径的时候,交给绑定的函数进行处理

    if err := http.ListenAndServe("localhost:1234",nil); err != nil {
    		log.Fatal("ListenAndServe:",err)
    	}
    
    • 1
    • 2
    • 3

    该段代码用于启动Web服务,并监听相应端口

    变量&常量&指针&赋值

    变量

    Go语言的变量声明使用var关键字,常量声明使用const关键字,语法如下:

    var name[类型]=[表达式]
    
    • 1

    在使用过程中,类型和表达式两者可省略其一,但不能同时省略,如果省略类型,Go会根据表达式推测得出类型,如果省略了表达式,Go会为变量赋予一个默认值
    数字类型默认值为0,布尔类型默认值为false,字符串类型默认值为“”,其他诸如接口、slice、指针、通道、函数的默认值为nil;如果是复合类型,例如结构体、其内部所有元素被赋予对应的默认值

    package main
    
    import (
    	"fmt"
    	"math/rand"
    )
    
    func main() {
    	//多个变量一起通过类型声明
    	var i, j, k int
    	fmt.Printf("i:%d,j:%d,k:%d", i, j, k)
    	fmt.Println()
    	//多个变量一起通过表达式声明
    	var a, b, c = 1, "s", true
    	fmt.Printf("a:%d,b:%s,c:%t", a, b, c)
    	fmt.Println()
    	//声明赋值的缩写
    	f := rand.Float64() * 100
    	fmt.Printf("f:%g", f)
    	fmt.Println()
    	m, n := 2, 1
    	fmt.Println(m, n)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    执行结果

    PS D:\book\ch01\1.2\var> go run .\main.go
    i:0,j:0,k:0
    a:1,b:s,c:true
    f:60.466028797961954
    2 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    常量

    Go语言定义常量使用的是const关键字,Go语言中的常量一般会用作全局常量,常量的值在程序编译的时候就确定了,之后不可再变

    定义单个常量
    const LENGTH=100
    const s1 = "test"
    const s2 string = "test"
    
    • 1
    • 2
    • 3

    同样的没有指明类型的声明,Go会根据等号右侧表达式的值推测出其类型,需要指出的是,这种用法成为无类型用法,无类型也是一种类型,它是一种比基本类型精度更高的类型,至少可达256位,比机器硬件精度更高,无类型在Go语言中有六种,无类型布尔、无类型整数、无类型文字符号、无类型浮点数、无类型复数和无类型字符串,无类型可以用来处理基本类型处理不了的数据,例如精度特别大的浮点数

    定义多个常量
    const(
    	SYS="Debian"
    	TYPE="pro"
    )
    
    • 1
    • 2
    • 3
    • 4
    常量生成器

    声明常量可以使用常量生成器iota,它可以通过枚举创建一系列相关的值,而且不需要明确定义类型,iota每次从0开始取值,逐次加1

    package main
    
    import "fmt"
    
    type data int
    
    const (
    	Zero data = iota
    	One
    	Two
    	Three
    	Four
    )
    
    const (
    	p2_0 = 1 << iota
    	p2_1
    	p2_2
    	p2_3
    )
    
    func main() {
    
    	fmt.Println(Zero)
    	fmt.Println(One)
    	fmt.Println(Two)
    	fmt.Println(Three)
    	fmt.Println(Four)
    	fmt.Println(p2_0)
    	fmt.Println(p2_1)
    	fmt.Println(p2_2)
    	fmt.Println(p2_3)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    执行结果

    PS D:\book\ch01\1.2\iota> go run .\main.go
    0
    1
    2
    3
    4
    1
    2
    4
    8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    指针

    假设有一个int型变量x,&x表示取x的地址,将此值赋给p,那么p就是指针,取得指针指向的值,使用*p

    var int x //x默认初始值为0
    p:=&x //p为整形指针,指向x
    fmt.Println(*p) //此时打印输出0
    *p=1 //类似于x=1
    fmt.Println(x) //此时打印输出1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Go官方文档中提到的Zero Value,在很多场景下被称为“零值”,在C语言中称为默认初始值

    可以使用指针来代替变量名,如果指针改变了变量值,会影响到变量名,本质上他们就是同一个内存空间,实际上复合类型也可以通过指针进行操作,复合类型内的具体元素同样有地址,并且可以通过指针进行操作,对于上边代码中的p我们称为指针类型,其默认值是nil,可以用过p==nil来判断是否取得地址,nil表示未成功取得

    package main
    import "fmt"
    func main(){
    	m:=1
    	selfPlusPointer(&m)
    	fmt.Println(m) //2
    	// selfPlus返回得是指针类型,所以要加上*号才能取到指针指向的变量值,否则只是个地址
    	fmt.Println(*selfPlus(1)) //2
    }
    // 定义了一个自增函数,接受的参数是一个int指针,函数体通过指针执行了自增,且函数没有返回值,因为通过指针直接修改了变量值
    func selfPlusPointer(n *int){
    	*n++
    }
    // 该函数接收一个整型参数,用一个临时变量暂时存储n的自增1的结果,然后再返回临时变量的指针类型
    func selfPlus(n int) *int{
    	t:=n+1
    	return &t
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在Go语言中除非显示的使用指针,否则所有的值传递都是具体值得赋值,包括符合结构

    Go语言还提供了new函数,用于创建一个不需要名称的变量,并可以直接赋值给一个指针

    p:=new(int) //p为*int类型
    fmt.Println(*p) //0
    
    • 1
    • 2

    赋值

  • 相关阅读:
    在Ubuntu中启用root用户登录SSH
    Mybatis—mapper配置文件xml位置
    leetCode 解法集锦
    算法训练 第三周
    【Pygame】 游戏开发 基础知识
    【75. 颜色分类】
    关于Gson的TypeToken
    Prometheus+grafana监控--初探
    【Docker】容器化应用程序的配置管理策略与实践
    canal实现mysql数据同步
  • 原文地址:https://blog.csdn.net/dawei_yang000000/article/details/128470676