我是靠谱客的博主 欢喜龙猫,最近开发中收集的这篇文章主要介绍go基本语法go基本语法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

go基本语法

文章目录

  • go基本语法
    • 数字类型
      • 整数:
      • 无符号整数:
      • 浮点型(IEEE-754 标准):
      • 复数
      • **格式化说明符**
      • 实例
    • 类型
      • 函数
        • 可以是一个确定的类型
        • 可拥有多种返回值
      • type关键字
    • 类型转换
    • 常量
      • 常量枚举
    • 变量-var
      • 易错
    • Bool值
    • 位运算
      • **二元运算符**
    • 算术运算符
    • 运算符优先级
    • ASCII
    • IF语句
    • for loop
    • switch
    • 切片
    • map
    • range
    • 函数
    • 指针
    • 结构体
      • 类成员函数

数字类型

Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码(详情参见 二的补码 页面)。

Go 也有基于架构的类型,例如:intuintuintptr

这些类型的长度都是根据运行程序所在的操作系统类型所决定的:

  • intuint 在 32 位操作系统上,它们均使用 32 位(4 个字节),在 64 位操作系统上,它们均使用 64 位(8 个字节)。
  • uintptr 的长度被设定为足够存放一个指针即可。

Go 语言中没有 float 类型。(Go语言中只有 float32float64)没有 double 类型。

与操作系统架构无关的类型都有固定的大小,并在类型的名称中就可以看出来:

整数:

  • int8(-128 -> 127)
  • int16(-32768 -> 32767)
  • int32(-2,147,483,648 -> 2,147,483,647)
  • int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)

无符号整数:

  • uint8(0 -> 255)
  • uint16(0 -> 65,535)
  • uint32(0 -> 4,294,967,295)
  • uint64(0 -> 18,446,744,073,709,551,615)

浮点型(IEEE-754 标准):

  • float32(± 1e-45 -> ± 3.4 * 1e38)
  • float64(± 5 * 1e-324 -> 107 * 1e308)

int 型是计算最快的一种类型。

整型的零值为 0,浮点型的零值为 0.0

float32 精确到小数点后 7 位,float64 精确到小数点后 15 位

你应该尽可能地使用 float64,因为 math 包中所有有关数学运算的函数都会要求接收这个类型。

你可以通过增加前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示 16 进制数(如:0xFF),以及使用 e 来表示 10 的连乘(如: 1e3 = 1000,或者 6.022e23 = 6.022 x 1e23)。

你可以使用 a := uint64(0) 来同时完成类型转换和赋值操作,这样 a 的类型就是 uint64

Go 中不允许不同类型之间的混合使用,但是对于常量的类型限制非常少,因此允许常量之间的混合使用

复数

两种类型:complex64;complex128

格式化说明符:%v

func main() {
var c1 complex64 = 5 + 10i
var c2 complex128 = 5 - 10i
var re float32 = 2
var im float32 = 3
var c = complex(re, im)
fmt.Println(c1)
fmt.Println(real(c1), imag(c2))
fmt.Printf("%v %v", c2, c)
}

输出

(5+10i)
5 -10
(5-10i) (2+3i)

格式化说明符

在格式化字符串里,%d 用于格式化整数(%x%X 用于格式化 16 进制表示的数字),%g 用于格式化浮点型(%f 输出浮点数,%e 输出科学计数表示法),%0nd 用于规定输出长度为 n 的整数,其中开头的数字 0 是必须的。

%n.mg 用于表示数字 n 并精确到小数点后 m 位,除了使用 g 之外,还可以使用 e 或者 f,例如:使用格式化字符串 %5.2e 来输出 3.4 的结果为 3.40e+00

实例

package main
import "fmt"
func main() {
var n int16 = 34
var m int32
// compiler error: cannot use n (type int16) as type int32 in assignment
//m = n
m = int32(n)
fmt.Printf("32 bit int is: %dn", m)
fmt.Printf("16 bit int is: %dn", n)
}

输出

32 bit int is: 34
16 bit int is: 34

类型

package main
import (
"fmt"
"math"
)
func main() {
var a = "initial" //可以省略类型说明符
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
fmt.Println(a, b, c, d, e, f)
fmt.Println(g)
const s string = "constant"
const h = 500000
const l = 3e20 / h
fmt.Println(s, h, l, math.Sin(h), math.Sin(l))
}

输出

initial 1 2 true 0 0
initialfoo
constant 500000 6e+14 0.17783120151825887 0.9538537219686818

变量(或常量)包含数据,这些数据可以有不同的数据类型,简称类型。使用 var 声明的变量的值会自动初始化为该类型的零值。类型定义了某个变量的值的集合与可对其进行操作的集合。

类型可以是基本类型,如:intfloatboolstring;结构化的(复合的),如:structarray、切片 (slice)、map、通道 (channel);只描述类型的行为的,如:interface

结构化的类型没有真正的值,它使用 nil 作为默认值

值得注意的是,Go 语言中不存在类型继承。

函数

可以是一个确定的类型

就是以函数作为返回类型。这种类型的声明要写在函数名和可选的参数列表之后,例如:

func FunctionName (a typea, b typeb) typeFunc

你可以在函数体中的某处返回使用类型为 typeFunc 的变量 var

return var

可拥有多种返回值

返回类型之间需要使用逗号分割,并使用小括号 () 将它们括起来,如:

func FunctionName (a typea, b typeb) (t1 type1, t2 type2)

返回的形式:

return var1, var2

这种多返回值一般用于判断某个函数是否执行成功 (true/false) 或与其它返回值一同返回错误消息(详见之后的并行赋值)。

type关键字

使用 type 关键字可以定义你自己的类型,也可以定义一个已经存在的类型的别名,如:

type IZ int

这里并不是真正意义上的别名,因为使用这种方法定义之后的类型可以拥有更多的特性,且在类型转换时必须显式转换。

然后我们可以使用下面的方式声明变量:

var a IZ = 5

这里我们可以看到 int 是变量 a 的底层类型,这也使得它们之间存在相互转换的可能

如果你有多个类型需要定义,可以使用因式分解关键字的方式,例如:

type (
IZ int
FZ float64
STR string
)

每个值都必须在经过编译后属于某个类型(编译器必须能够推断出所有值的类型),因为 Go 语言是一种静态类型语言。

类型转换

go不存在隐式转换

只能在定义正确的情况下成功,例如从取值范围小到大;精度从小到大

具有相同底层类型的变量之间可以相互转换

a := 5.0
b := int(a)

常量

一个没有指定类型的常量被使用时,会根据其使用环境而推断出它所需要具备的类型。

换句话说,未定义类型的常量会在必要时刻根据上下文来获得相关类型。

const PI=3,1415
var n int
f(n + 5) // 无类型的数字型常量 “5” 它的类型在这里变成了 int

因为在编译期间自定义函数均属于未知,因此无法用于常量的赋值,但内置函数可以使用,如:len()

var c = "string"
const c = getnum() //未定义,所以是错误的
const c2 = len(s)

当常量赋值给一个精度过小的数字型变量时,可能会因为无法正确表达常量所代表的数值而导致溢出,这会在编译期间就引发错误。另外,常量也允许使用并行赋值的形式

const beef, two, c = "eat", 2, "veg"
const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6
//常量可以进行枚举
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)

常量枚举

类似于c++当中的enum

关于iota:每遇到一个新的常量块或单个常量声明(每次遇到一个const关键字)iota都重置为0

const (
a=iota //0
b=iota //1
c=iota //2
d=5
e //5
)
// 赋值两个常量,iota 只会增长一次,而不会因为使用了两次就增长两次
const (
Apple, Banana = iota + 1, iota + 2 // Apple=1 Banana=2
Cherimoya, Durian
// Cherimoya=2 Durian=3
Elderberry, Fig
// Elderberry=3, Fig=4
)
// 使用 iota 结合 位运算 表示资源状态的使用案例
const (
Open = 1 << iota
// 0001
Close
// 0010
Pending
// 0100
)
const (
_
= iota
// 使用 _ 忽略不需要的 iota
KB = 1 << (10 * iota)
// 1 << (10*1)
MB
// 1 << (10*2)
GB
// 1 << (10*3)
TB
// 1 << (10*4)
PB
// 1 << (10*5)
EB
// 1 << (10*6)
ZB
// 1 << (10*7)
YB
// 1 << (10*8)
)

变量-var

变量的类型放在变量的名称后面,防止类型分不清

所有的内存在 Go 中都是经过初始化的,字符串指针为nil,其余的则为0

var a, b *int
var a int
var b bool
var str string
//全局变量
var (
a int
b bool
str string
)

不申明类型,go可以通过值来自行推断

var a = 15
var b = false
var str = "Go says hello to the world!"

在函数体内声明局部变量

这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。使用操作符 := 可以高效地创建一个新的变量,称之为初始化声明。

a := 1

声明包级别的全局变量

var (
HOME = os.Getenv("HOME")
USER = os.Getenv("USER")
GOROOT = os.Getenv("GOROOT") //获取环境变量中的值
)

在 Go 语言中,指针属于引用类型,其它的引用类型还包括 slices,maps和 channel。被引用的变量会存储在堆中,以便进行垃圾回收,且比栈拥有更大的内存空间

一些省略写法

//并行赋值
//并行赋值也被用于当一个函数返回多个返回值时,比如这里的 `val` 和错误 `err` 是通过调用 `Func1` 函数同时得到:`val, err = Func1(var1)`。
a, b, c := 5, 7, "abc"
//交换值
a,b=b,a

抛弃值

_ 实际上是一个只写变量,你不能得到它的值。这样做是因为你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值

_,b=5,7

易错

package main
import (
"fmt"
"./trans"
)
var twoPi = 2 * trans.Pi
func main() {
fmt.Printf("2*Pi = %gn", twoPi) // 2*Pi = 6.283185307179586
}

输出

原因: ':='不用于全局变量的声明

G00

Bool值

可以使用 %t 来表示你要输出的值为布尔型。

var aVar = 10
aVar != 5 -> true
aVar != 10 -> false

位运算

条件:只能用于整数;且拥有等长位模式

%b 是用于表示位的格式化标识符

二元运算符

  • 按位与 &:有0则0

  • 按位或 |:有1则1

  • 按位异或 ^:同为0,异为1

  • 位清除 &^:将指定位置上的值设置为 0

    package main
    import "fmt"
    func main() {
    var x uint8 = 15
    var y uint8 = 4
    fmt.Printf("%08bn", x &^ y);
    // 00001011
    }
    

一元运算符

  • 按位补足 ^

    该运算符与异或运算符一同使用,即 m^x,对于无符号 x 使用 “全部位设置为 1” 的规则,对于有符号 x 时使用 m=-1。例如:

    ^10 = -01 ^ 10 = -11
    
  • 位左移 <<

    • 用法:bitP << n
    • bitP 的位向左移动 n 位,右侧空白部分使用 0 填充;如果 n 等于 2,则结果是 2 的相应倍数,即 2 的 n 次方。例如:
  • 位右移 >>

    • 用法:bitP >> n
    • bitP 的位向右移动 n 位,左侧空白部分使用 0 填充;如果 n 等于 2,则结果是当前值除以 2 的 n 次方。

当希望把结果赋值给第一个操作数时,可以简写为 a <<= 2 或者 b ^= a & 0xffffffff

算术运算符

常见可用于整数和浮点数的二元运算符有 +-*/

(相对于一般规则而言,Go 在进行字符串拼接时允许使用对运算符 + 的重载,但 Go 本身不允许开发者进行自定义的运算符重载)

/ 对于整数运算而言,结果依旧为整数,例如:9 / 4 -> 2

取余运算符只能作用于整数:9 % 4 -> 1

整数除以 0 可能导致程序崩溃,将会导致运行时的恐慌状态(如果除以 0 的行为在编译时就能被捕捉到,则会引发编译错误);[第 13 章](file:///D:/self/资料/go/the-way-to-go/eBook/13.0.md) 将会详细讲解如何正确地处理此类情况。

浮点数除以 0.0 会返回一个无穷尽的结果,使用 +Inf 表示

你可以将语句 b = b + a 简写为 b += a,同样的写法也可用于 -=*=/=%=

对于整数和浮点数,你可以使用一元运算符 ++(递增)和 --(递减)

同时,带有 ++-- 的只能作为语句,而非表达式,因此 n = i++ 这种写法是无效的,其它像 f(i++) 或者 a[i]=b[i++] 这些可以用于 C、C++ 和 Java 中的写法在 Go 中也是不允许的。

在运算时 溢出 不会产生错误,Go 会简单地将超出位数抛弃

需要范围无限大的整数或者有理数(意味着只被限制于计算机内存),你可以使用标准库中的 big 包,该包提供了类似 big.Intbig.Rat 这样的类型

运算符优先级

优先级
运算符
7
^ !
6
* / % << >> & &^
5
+ - | ^
4
== != < <= >= >
3
<-
2
&&
1
||

ASCII

var ch byte = 65
var ch byte = 'x41'

IF语句

判断条件不加括号,if之后必须加{},其余跟c类似

package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
}

for loop

go语言中没有while系列循环,只有for

package main
import "fmt"
func main() {
for {
fmt.Println("loop")
break
}
for j := 7; j < 9; j++ {
fmt.Println(j)
}
for n := 0; n < 5; n++ {
if n%2 == 0 {
fmt.Println(n)
continue
}
}
}

输出

loop
7
8
0
2
4

switch

变量可以不仅仅是数字,也可以是字符串

不需要加break

package main
import (
"fmt"
"time"
)
func main() {
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's befor noon")
default:
fmt.Println("It's afternoon")
}
}

输出

two
It's afternoon

切片

package main
import "fmt"
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(s[2:5])
fmt.Println(s[:5])
fmt.Println(s[2:])
good := []string{"g", "o", "o", "d"}
fmt.Println(good)
}

输出

get: c
len: 3
[a b c d e f]
[a b c d e f]
[c d e]
[a b c d e]
[c d e f]
[g o o d]

map

随机顺序

package main
import "fmt"
func main() {
m := make(map[string]int) //类似于一个类型配另一个类型(可相同)
m["one"] = 1
m["two"] = 2
fmt.Println(m, len(m), m["one"], m["unknown"])
r, ok := m["unknown"]
fmt.Println(r, ok)
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}

输出

map[one:1 two:2] 2 1 0
0 false
map[one:1 two:2] map[one:1 two:2]

range

package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += sum
if sum == 2 {
fmt.Println("index:", i, "num:", num)
}
}
fmt.Println(sum)
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v)
}
for k := range m {
fmt.Println("key", k)
}
}

输出

0
a A
b B
key b
key a

函数

package main
import "fmt"
func add(a int, b int) int { //数据类型后置
return a + b
}
func add2(a, b int) int {//类型相同可省略
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res)
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok)
}

输出

3
A true

指针

对传入的参数作出修改

package main
import "fmt"
func add(a *int) {
*a += 2
}
func add2(b int) {
b += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n)
add(&n)
fmt.Println(n)
}

输出

5
7

结构体

package main
import (
"fmt"
)
type user struct {
name
string
password string
}
func checkpassword(u user, password string) bool {
return u.password == password
}
func check2(u *user, password string) bool {
return u.password == password
}
func main() {
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
fmt.Println(a, b, c, d)
fmt.Println(checkpassword(a, "haha"))
fmt.Println(check2(&a, "haha"))
}

输出

{wang 1024} {wang 1024} {wang 1024} {wang 1024}
false
false

类成员函数

package main
import "fmt"
type user struct {
name
string
password string
}
func (u *user) check2(password string) bool {
return u.password == password
}
func (u *user) reset(password string) { //从一个普通函数变成类成员函数
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.reset("2048")
fmt.Println(a.check2("2048"))
}

输出

true

ord == password
}

func check2(u *user, password string) bool {
return u.password == password
}

func main() {
a := user{name: “wang”, password: “1024”}
b := user{“wang”, “1024”}
c := user{name: “wang”}
c.password = “1024”
var d user
d.name = “wang”
d.password = “1024”

fmt.Println(a, b, c, d)
fmt.Println(checkpassword(a, "haha"))
fmt.Println(check2(&a, "haha"))

}


输出

{wang 1024} {wang 1024} {wang 1024} {wang 1024}
false
false


### 类成员函数
```go
package main
import "fmt"
type user struct {
name
string
password string
}
func (u *user) check2(password string) bool {
return u.password == password
}
func (u *user) reset(password string) { //从一个普通函数变成类成员函数
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.reset("2048")
fmt.Println(a.check2("2048"))
}

输出

true

最后

以上就是欢喜龙猫为你收集整理的go基本语法go基本语法的全部内容,希望文章能够帮你解决go基本语法go基本语法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部