Go语言基础之基本语法

基本结构

package main

import "fmt"

func main() {
	fmt.Println("Hello,World!")
}
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)
	}
}
  • 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>

第二段代码的执行

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 你好,世界!

同时打开浏览器,访问地址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)
	}

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

变量&常量&指针&赋值

变量

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

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

在使用过程中,类型和表达式两者可省略其一,但不能同时省略,如果省略类型,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)
}

执行结果

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

常量

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

定义单个常量
const LENGTH=100
const s1 = "test"
const s2 string = "test"

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

定义多个常量
const(
	SYS="Debian"
	TYPE="pro"
)
常量生成器

声明常量可以使用常量生成器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)
}

执行结果

PS D:\book\ch01\1.2\iota> go run .\main.go
0
1
2
3
4
1
2
4
8

指针

假设有一个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

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
}

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

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

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

赋值

你可能感兴趣的:(计算机语言系列,golang,iphone,xcode)