Go语言的基本概念与语法

这篇具有很好参考价值的文章主要介绍了Go语言的基本概念与语法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

包package

每个 Go 程序都是由包组成的.

程序从 main包开始运行.

本程序通过导入路径 "fmt" and "math/rand"来使用这两个包.

按照约定,包名与导入路径的最后一个元素相同。例如,"math/rand" 包中的源码均以packagerand` 语句开始.

注意: 执行这些程序的环境是确定性的 所以每次运行示例程序 rand.Intn 都会返回相同的数字.

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	fmt.Println("My favorite number is", rand.Intn(10))
}

Imports(导入)

此代码将导入分组到带括号的"factored(分解)"导入语句中.

您还可以编写多个导入语句,例如:

import "fmt"
import "math"
或者
import (
	"fmt"
	"math"
)

但是使用factored import语句是一种很好的风格.

基本数据类型

bool

布尔值是一组布尔值,truefalse

默认值:false

string

字符串是所有 8 位字节字符串的集合,通常必须表示 UTF-8 编码的文本。字符串可能为空,但 不是零。字符串类型的值是不可变的。

默认值:“”

int

int 是大小至少为 32 位的有符号整数类型。这是一个非重复类型,而不是 int32 的别名。

默认值:0

int类型还有其他相关类型:

  • int8:是所有有符号 8 位整数的集合。 范围:-2 ^8 到 2 ^8 - 1。
  • int16:是所有有符号 16 位整数的集合。 范围:-2 ^16 到 2 ^16 - 1。
  • int32:是所有有符号 32 位整数的集合。 范围:-2 ^32 到 2 ^32 - 1。
  • int64:是所有有符号 64 位整数的集合。 范围:-2 ^64 到 2 ^64 - 1。
  • uint:一种无符号整数类型,大小至少为32位。这是一个不同的类型,而不是 uint32 的别名。
  • uint8:是所有无符号 8 位整数的集合。 范围:0 到 2 ^8 - 1。
  • uint16:是所有无符号 16 位整数的集合。 范围:0 到 2 ^16 - 1。
  • uint32:是所有无符号 32 位整数的集合。 范围:0 到 2 ^32 - 1。
  • uint64:是所有无符号 64 位整数的集合。 范围:0 到 2 ^64 - 1。
  • uintptr:是一个整数类型,它足够大,可以容纳任何指针。

注意:
int, uint, and uintptr 在 32 位系统上通常为 32 位宽,在 64 位系统上则为 64 位宽. 当你需要一个整数值时,你应该使用 int 除非你有特定的理由使用一个固定大小或无符号的整数类型。

byte

字节是 uint8 的别名,在所有方面都等效于 uint8。用于区分字节值和 8 位无符号 整数值。

rune

rune 是 Int32 的别名,在所有方面都等同于 Int32。用于区分字符值和整数值。

float

  • float32:float32 是所有 IEEE-754 32 位浮点数的集合。
  • float64:float64 是所有 IEEE-754 64 位浮点数的集合。

complex

复数是由两个浮点数表示的,其中一个表示实部(real),一个表示虚部(imag)。

  • complex64:是所有复数的集合,float32 实数和虚部。
  • complex128:是所有复数的集合,float64 实数和虚部。复数的默认类型。

变量

变量声明

var 语句用于声明一个变量列表,跟函数的参数列表一样,类型在最后。

var 语句可以出现在包或函数级别。

语法:var i int

var声明可以包含初始化程序,每个变量一个。如果存在初始化器,则可以省略类型;

在函数内部, 可以使用 := 短赋值语句来代替具有隐式类型的 var 声明。

但是,在函数外部, 每个语句都以关键字 (var, func, 等) 因此 := 结构不可用。

觉得每行都用 var 声明变量比较烦琐?没关系,还有一种为懒人提供的定义变量的方法:

var (
    a int
    b string
    c []float32
    d func() bool
    e struct {
        x int
    }
)

使用关键字 var 和括号,可以将一组变量定义放在一起。

变量的初始化

可以这么写:var hp int = 100 也可以省略int直接这么写:var hp = 100 下边可以有为什么可以这么写的原因。还有短变量初始化操作: hp := 100

匿名变量

匿名变量的特点是一个下画线“”,“”本身就是一个特殊的标识符,被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃,因此这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其它变量进行赋值或运算。使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。例如:

func GetData() (int, int) {
    return 100, 200
}
func main(){
    a, _ := GetData()
    _, b := GetData()
    fmt.Println(a, b)
}

常量

常量像变量一样声明,但使用 const 关键字。常量可以是字符、字符串、布尔值或数字值。不能使用 := 语法声明常量。

数字常量是高精度 。无类型常量采用其上下文所需的类型。(一个 int 最多可以存储 64 位整数,有时更少.)

和变量声明一样,可以批量声明多个常量:

const (
    e  = 2.7182818
    pi = 3.1415926
)

iota 常量生成器

常量声明可以使用 iota 常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个 const 声明语句中,在第一个声明的常量所在的行,iota 将会被置为 0,然后在每一个有常量声明的行加一。

type Weekday int
const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

for语句

for语法结构

Go 只有一个循环结构,即 for 循环.

基本 for 循环包含三个由分号分隔的组件:

  • init 语句: 在第一次迭代之前执行
  • 条件表达式:在每次迭代前求值
  • post 语句:在每次迭代结束时执行

init语句通常是一个简短的变量声明,并且在那里声明的变量仅在该 for 语句的范围内可见.

一旦布尔条件评估为 false ,循环将停止迭代。init 和 post 语句是可选的;如果省略循环条件,它将永远循环,因此可以紧凑地表示无限循环.

注意: 与 C、Java 或 JavaScript 等其他语言不同,for 语句的三个组件周围没有括号,并且大括号 { } 始终需要。

package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}

for 是Go中的while

C和Java 的 while 在 Go 中叫做 for

package main

import "fmt"

func main() {
	sum := 1
	for sum < 1000 {
		sum += sum
	}
	fmt.Println(sum)
}

if语句

Go 的 if 语句就像它的 for 循环;表达式不需要用括号 ( ) 括起来,但需要大括号 { } .

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string {
	if x < 0 {
		return sqrt(-x) + "i"
	}
	return fmt.Sprint(math.Sqrt(x))
}

func main() {
	fmt.Println(sqrt(2), sqrt(-4))
}

就像 forif 语句可以在条件之前以短语句执行。语句声明的变量作用域仅在 if 之内。

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

If 和 else

if 短语句中声明的变量也可以在任何 else 块中使用。

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// can't use v here, though
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

switch

switch 语句是编写一连串 if - else 语句的简便方法。它运行其值等于条件表达式的第一个 case。

Go 的 switch 类似于 C、C++、Java、JavaScriptPHP 中的 switch,只是 Go 只运行选定的case,而不是所有后续case。

实际上,Go 自动提供了在这些语言中每个 case 后面所需的 break 语句。另一个重要的区别是 Go 的 switchcase 不需要是常量,所涉及的值也不需要是整数。

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os {
		case "darwin":
			fmt.Println("OS X.")
		case "linux":
			fmt.Println("Linux.")
		default:
			// freebsd, openbsd,
			// plan9, windows...
			fmt.Printf("%s.\n", os)
	}
}

switch 的求值顺序

switch 的 case 语句从上到下顺次执行,直到匹配成功时停止。 如果 i==0不调用 f

switch i {
case 0:
case f():
}

注意: Go playground 场中的时间总是从 2009-11-10 23:00:00 UTC 开始。

没有条件的switch

没有条件的 Switch 同 switch true 一样。这种构造可以是编写长 if-then-else 链的一种干净方式.

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("Good morning!")
	case t.Hour() < 17:
		fmt.Println("Good afternoon.")
	default:
		fmt.Println("Good evening.")
	}
}

defer语句

defer 语句推迟函数的执行,直到周围的函数返回。

延迟调用的参数会立即计算,但直到周围的函数返回时才会执行函数调用。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}

Stacking defers(defer栈)

延迟的函数调用被推送到栈上。当函数返回时,其延迟调用将按后进先出顺序执行。

package main

import "fmt"

func main() {
	defer fmt.Println("world")
	fmt.Println("hello")
}

结果:

hello
world

go中关键字

Go语言中的关键字一共有 25 个:

break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

类型转换

在 Go 中不同类型的项之间的赋值需要显式转换。比如

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

或者

i := 42
f := float64(i)
u := uint(f)

类型推断

当声明一个变量而不指定显式类型 (通过使用 := syntax 或 var = 表达式语法), 变量的类型是从右侧的值推断出来的.

当右值声明了类型时,新变量的类型与其相同:

var i int
j := i // j is an int

但是,当右侧包含无类型的数字常量, 新的变量可以是 int, float64, 或 complex128 取决于常量的精度:

i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

Go函数

一个函数可以接受零个或多个参数.

在本例中,add 接受两个 int 类型的参数.

请注意,类型在变量名 之后 .

package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}

当两个或多个连续命名函数参数共享一个类型时,除了最后一个之外,可以省略所有类型.

在这个例子中,我们缩短

x int, y int
可以写成
x, y int

Multiple results(多值返回)

一个函数可以返回任意数量的结果。该 swap 函数返回两个字符串。

package main

import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}

Named return values(命名的返回值)

Go 的返回值可以命名。如果是这样,它们将被视为在函数顶部定义的变量。

这些名称应用于记录返回值的含义。

不带参数的 return 语句返回命名的返回值,这被称为“裸”返回。

裸返回语句应该只在短函数中使用,就像这里显示的例子一样。它们会损害较长函数的可读性。

package main

import "fmt"

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

func main() {
	fmt.Println(split(17))
}

函数值

函数也是值。它们可以像其他值一样传递,函数值可以用作函数参数和返回值

package main

import (
	"fmt"
	"math"
)

func compute(fn func(float64, float64) float64) float64 {
	return fn(3, 4)
}

func main() {
	hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
	}
	fmt.Println(hypot(5, 12))

	fmt.Println(compute(hypot))
	fmt.Println(compute(math.Pow))
}

函数闭包

Go 函数可以是闭包。闭包是引用其主体外部的变量的函数值。该函数可以访问并分配给引用的变量;从这个意义上说,函数是“绑定”到变量的.

例如, adder 函数返回一个闭包。每个闭包都绑定到它自己的 sum 变量.

Go语言nil:空值/零值

在Go语言中,布尔类型的零值(初始值)为 false,数值类型的零值为 0,字符串类型的零值为空字符串"",而指针、切片、映射、通道、函数和接口的零值则是 nil。

nil 是Go语言中一个预定义好的标识符,有过其他编程语言开发经验的开发者也许会把 nil 看作其他语言中的 null(NULL),其实这并不是完全正确的,因为Go语言中的 nil 和其他语言中的 null 有很多不同点。

nil 标识符是不能比较的

这点和 python 等动态语言是不同的,在 python 中,两个 None 值永远相等。对于 nil 来说是一种未定义的操作。

nil 不是关键字或保留字

nil 并不是Go语言的关键字或者保留字,也就是说我们可以定义一个名称为 nil 的变量,比如下面这样:var nil = errors.New("my god")

虽然上面的声明语句可以通过编译,但是并不提倡这么做。

nil 没有默认类型

package main
import (
    "fmt"
)
func main() {
    fmt.Printf("%T", nil)
    print(nil)
}

运行结果如下所示:

.\main.go:9:10: use of untyped nil

不同类型 nil 的指针是一样的

package main
import (
    "fmt"
)
func main() {
    var arr []int
    var num *int
    fmt.Printf("%p\n", arr)
    fmt.Printf("%p", num)
}

结果:
0x0
0x0

通过运行结果可以看出 arr 和 num 的指针都是 0x0。

nil 是 map、slice、pointer、channel、func、interface 的零值

零值是Go语言中变量在声明之后但是未初始化被赋予的该类型的一个默认值。

不同类型的 nil 值占用的内存大小可能是不一样的

一个类型的所有的值的内存布局都是一样的,nil 也不例外,nil 的大小与同类型中的非 nil 类型的大小是一样的。但是不同类型的 nil 值的大小可能不同。

具体的大小取决于编译器和架构,上面打印的结果是在 64 位架构和标准编译器下完成的,对应 32 位的架构的,打印的大小将减半。


--------------------------------------------------------------欢迎叨扰此地址---------------------------------------------------------------

本文作者:Java技术债务
原文链接:https://cuizb.top/myblog/article/detail/1687832300
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。文章来源地址https://www.toymoban.com/news/detail-509090.html

到了这里,关于Go语言的基本概念与语法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Go语言模板语法

    连接前后端的符号: {{}} 模板语法都包含在 {{}} 之中,其中 {{.}} 中的 . 表示当前对象.在传入一个结构体对象时,可以根据 \\\".\\\" 来访问结构体的对应字段.如果是复合类型数据,则可以通过 {{.FiledName}} 来访问它的字段, FiledName 是指对应go代码中的结构体变量名 伪代码例子: 这样后端数

    2024年02月13日
    浏览(40)
  • GO语言语法结构

    包声明 引入包 函数 变量 语句  表达式 注释 如这段代码块根据上面的语法结构进行逐行解释 第一行的 package main 是定义一个包名,必须在源文件中非注释的第一行指明这个文件属于哪个包,如 package main ,可以代表一个独立执行的程序,每个GO应用程序都包含一个名为 main

    2024年02月13日
    浏览(46)
  • MySQL 基本概念 基础用法 增删改查(特殊查询)语法 详细篇

    今天来分享一期MySQL的基本用法(增删改查 对库 对表 对值) 目录 MySQL的基础概念  SQL 语言的主要分类 DDL(数据定义语言) DML(数据操控语言) DQL(数据库查询语言) DCL(数据库控制语言) 基础语法 增 库的操作 表操作 列操作 值操作 删 删除库 删除表 删除值 改 修改表名 更新数

    2024年03月16日
    浏览(47)
  • 【Verilog数字系统设计(夏宇闻)4-----Verilog语法的基本概念2】

    下面先介绍几个简单的Verilog HDL程序,从中了解Verilog模块的特性。 例1 如图所示的二选一多路选择器的Verilog HDL程序如下: 从例1中很容易理解模块muxtwo的作用。它是一个如图所示的二选一多路器,输出out与输入a一致,还是与输入b一致,由sl的电平决定。当控制信号sl为非(低

    2023年04月08日
    浏览(43)
  • Go 语言面试题(一):基础语法

    := 声明+赋值 = 仅赋值 指针用来保存变量的地址。 例如 运算符,也称为解引用运算符,用于访问地址中的值。 &运算符,也称为地址运算符,用于返回变量的地址。 允许 Go 没有异常类型,只有错误类型(Error),通常使用返回值来表示异常状态。 Goroutine 是与其他函数或方

    2024年02月14日
    浏览(47)
  • 扒一扒Go语言中的“语法糖”

    最近学习Golang语言的过程中,我发现Golang(后面简称Go)中的语法糖还蛮多的,有些语法糖还让会让人很懵逼。那么接下来,让我以一个曾经的 Java CURD boy,来说一说 Go 中的语法糖。 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J.

    2024年01月24日
    浏览(31)
  • 【C/C++套接字编程】套接字的基本概念与基础语法

    TCP/UDP实验为牵引,学习套接字编程的相关知识,再进一步深化对TCP/UDP的理解 目录 前言 Socket编程语法 1. 套接字及创建 什么是套接字? 创建套接字 2. 端口绑定 3. 收发信息 与recv()函数的比较: 与send()函数的比较: 编程实例  总结 系列博客 【C/C++套接字编程】TCP协议通信的

    2024年02月09日
    浏览(47)
  • 走进 Go 语言基础语法 | 青训营 (1)

    Powered by: NEFU AB-IN Go 语言入门指南:基础语法和常用特性解析 go.mod 这个文件里记录了当前项目里所有依赖包的 git 仓库地址以及对应的 版本号 ,来解决了包依赖管理的问题,后续在构建编译时,就会根据对应的版本号去拉取依赖包。 注意, 如果当前的项目是要给外部使用的

    2024年02月14日
    浏览(43)
  • C语言中常见的一些语法概念和功能

    常用代码:  程序入口: int main() 函数用于定义 程序的入口点 。 输出:使用 printf() 函数可以在控制台 打印输出 。 输入:使用 scanf() 函数可以接收 用户的输入 。 条件判断:使用 if-else 语句可以根据 条件执行不同的代码块 。 循环结构:使用 for 循环、 while 循环或 do-whil

    2024年02月11日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包