Go语言语法基础

devtools/2024/9/24 22:26:29/

Go语言语法基础

  • 1.Go项目构建及编译
  • 2.下划线的用处
  • 3.Go语言变量与常量
    • 变量命名规范
    • 变量声明与初始化
    • 常量
  • 4.Go语言基本数据类型
    • 整型
    • 浮点型
    • 复数
    • 布尔型
    • 指针
    • 字符串
      • 窥探字符串类型
      • 字符串内建函数
      • 字符串和数字的转换

1.Go项目构建及编译

一个Go工程中主要包含以下三个目录:

src:源代码文件
pkg:包文件
bin:相关bin文件

我们可以引用别人的包也可以发布自己的包,但是为了防止不同包的项目名冲突,我们通常使用顶级域名来作为包名的前缀,这样就不担心项目名冲突的问题了

因为不是每个个人开发者都拥有自己的顶级域名,所以目前流行的方式是使用个人的github用户名来区分不同的包:

举个例子:张三和李四都有一个名叫studygo的项目,那么这两个包的路径就会是:

import "github.com/zhangsan/studygo"

和:

import "github.com/lisi/studygo"

2.下划线的用处

1、下划线在import中

当导入一个包时,该包下的文件里所有init()函数都会被执行,然而,有些时候我们并不需要把整个包都导入进来,仅仅是是希望它执行init()函数而已。这个时候就可以使用 import 引用该包。即使用import _ 包路径只是引用该包,仅仅是为了调用init()函数,无法通过包名来调用包中的其他函数

2、下划线在代码中

下划线意思是忽略这个变量,意思是那个位置本应赋给某个值,但是咱们不需要这个值,这样编译器可以更好的优化,任何类型的单个值都可以丢给下划线,例如:

package mainimport ("os"
)func main() {buf := make([]byte, 1024)f, _ := os.Open("/Users/***/Desktop/text.txt")defer f.Close()for {n, _ := f.Read(buf)if n == 0 {break    }os.Stdout.Write(buf[:n])}
}

3.Go语言变量与常量

变量命名规范

1、Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线

2、大写字母和小写字母是不同的:heapSortHeapsort是两个不同的名字

3、如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问。

名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的,那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问。包本身的名字一般总是用小写字母

4、通常来说,如果一个名字的作用域比较大,生命周期也比较长,那么用长的名字将会更有意义

5、Go语言程序员推荐使用 驼峰式 命名,当名字由几个单词组成时优先使用大小写分隔,而不是优先用下划线分隔。因此,在标准库有QuoteRuneToASCIIparseRequestLine这样的函数命名

变量声明与初始化

Go语言主要有四种类型的声明语句:varconsttypefunc,分别对应变量、常量、类型和函数实体对象的声明

go语言中还支持批量变量声明,例如:

var (a stringb intc boold float32
)

var声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值。语法如下:

var 变量名字 类型 = 表达式

其中类型= 表达式两个部分可以省略其中的一个。如果省略的是类型信息,那么将根据初始化表达式来推导变量的类型信息。如果初始化表达式被省略,那么将用零值初始化该变量,例如:

func main() {var s stringvar d = 12fmt.Println(s)fmt.Println(d)
}

在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导,例如:

func main() {i := 100fmt.Println(i)
}

因为简洁和灵活的特点,简短变量声明被广泛用于大部分的局部变量的声明和初始化

这里有一个比较微妙的地方:简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了,那么简短变量声明语句对这些已经声明过的变量就只有赋值行为

例如:

在下面的代码中,第一个语句声明了in和err两个变量。在第二个语句只声明了out一个变量,然后对已经声明的err进行了赋值操作

in, err := os.Open(infile)
// ...
out, err := os.Create(outfile)

常量

一个常量的声明语句定义了常量的名字,和变量的声明语法类似,常量的值不可修改,这样可以防止在运行期被意外或恶意的修改

所有常量的运算都可以在编译期完成,这样可以减少运行时的工作,也方便其他编译优化。当操作数是常量时,一些运行时的错误也可以在编译时被发现,例如整数除零、字符串索引越界、任何导致无效浮点数的操作等

常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex和unsafe.Sizeof

iota 常量生成器

iota是go语言的常量计数器,只能在常量的表达式中使用。 iota在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次

例如:周日将对应0,周一为1,如此等等

type Weekday intconst (Sunday Weekday = iotaMondayTuesdayWednesdayThursdayFridaySaturday
)

我们也可以在复杂的常量表达式中使用iota,下面是一个更复杂的例子,每个常量都是1024的幂:

const (_ = 1 << (10 * iota)KiB // 1024MiB // 1048576GiB // 1073741824TiB // 1099511627776             (exceeds 1 << 32)PiB // 1125899906842624EiB // 1152921504606846976ZiB // 1180591620717411303424    (exceeds 1 << 64)YiB // 1208925819614629174706176
)

4.Go语言基本数据类型

整型

Go语言同时提供了有符号和无符号类型的整数运算。有int8、int16、int32和int64四种截然不同大小的有符号整数类型,分别对应8、16、32、64bit大小的有符号整数,与此对应的是uint8、uint16、uint32和uint64四种无符号整数类型

还有两种一般对应特定CPU平台机器字大小的有符号和无符号整数intuint;其中int是应用最广泛的数值类型

无符号数往往只有在位运算或其它特殊的运算场景才会使用,就像bit集合、分析二进制文件格式或者是哈希和加密操作等。它们通常并不用于仅仅是表达非负数量的场合

最后,还有一种无符号的整数类型uintptr,没有指定具体的bit大小但是足以容纳指针。uintptr类型只有在底层编程时才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方

算术运算符+、-、*和/可以适用于整数、浮点数和复数,但是取模运算符%仅用于整数间的运算

对于每种类型T,如果转换允许的话,类型转换操作T(x)将x转换为T类型,例如:

func main() {f := 3.141 // a float64i := int(f)fmt.Println(f, i) // "3.141 3"f = 1.99fmt.Println(int(f)) // "1"
}

任何大小的整数字面值都可以用以0开始的八进制格式书写,例如0666;或用以0x0X开头的十六进制格式书写,例如0xdeadbeef。十六进制数字可以用大写或小写字母。如今八进制数据通常用于POSIX操作系统上的文件访问权限标志,十六进制数字则更强调数字值的bit位模式

当使用fmt包打印一个数值时,我们可以用%d、%o或%x参数控制输出的进制格式,就像下面的例子:

func main() {o := 0666fmt.Printf("%d %[1]o %#[1]o\n", o) // "438 666 0666"x := int64(0xdeadbeef)fmt.Printf("%d %[1]x %#[1]x %#[1]X\n", x)// Output:// 3735928559 deadbeef 0xdeadbeef 0XDEADBEEF
}

请注意fmt的两个使用技巧:

1、通常Printf格式化字符串包含多个%参数时将会包含对应相同数量的额外操作数,但是%之后的[1]副词告诉Printf函数再次使用第一个操作数

2、第二,%后的#副词告诉Printf在用%o、%x或%X输出时生成0、0x或0X前缀

浮点型

Go语言提供了两种精度的浮点数,float32和float64

一个float32类型的浮点数可以提供大约6个十进制数的精度,而float64则可以提供约15个十进制数的精度;通常应该优先使用float64类型

小数点前面或后面的数字都可能被省略(例如.707或1.)。很小或很大的数最好用科学计数法书写,通过e或E来指定指数部分:

const Avogadro = 6.02214129e23  // 阿伏伽德罗常数
const Planck   = 6.62606957e-34 // 普朗克常数

例子:打印e的幂,打印精度是小数点后三个小数精度和8个字符宽度:

for x := 0; x < 8; x++ {fmt.Printf("x = %d e^x = %8.3f\n", x, math.Exp(float64(x)))
}

复数

Go语言提供了两种精度的复数类型:complex64complex128,分别对应float32float64两种浮点数精度。内置的complex函数用于构建复数,内建的realimag函数分别返回复数的实部和虚部:

func main() {var x complex128 = complex(1, 2) // 1+2ivar y complex128 = complex(3, 4) // 3+4ifmt.Println(x * y)               // "(-5+10i)"fmt.Println(real(x * y))         // "-5"fmt.Println(imag(x * y))         // "10"
}

上面x和y的声明语句还可以简化:

x := 1 + 2i
y := 3 + 4i

如果一个浮点数面值或一个十进制整数面值后面跟着一个i,例如3.141592i或2i,它将构成一个复数的虚部,复数的实部是0:

fmt.Println(1i * 1i) // "(-1+0i)"

另外我,复数也可以用==和!=进行相等比较。只有两个复数的实部和虚部都相等的时候它们才是相等的

布尔型

一个布尔类型的值只有两种:true和false

在Go语言中,布尔值并不会隐式转换为数字值0或1

指针

一个指针的值是另一个变量的地址。一个指针对应变量在内存中的存储位置。通过指针,我们可以直接读或更新对应变量的值,而不需要知道该变量的名字

如果用“var x int”声明语句声明一个x变量,那么&x表达式(取x变量的内存地址)将产生一个指向该整数变量的指针,指针对应的数据类型是*int,指针被称之为“指向int类型的指针

func main() {x := 1p := &xfmt.Println(*p) // "1"*p = 2fmt.Println(x) // "2"
}

任何类型的指针的零值都是nil。如果p指向某个有效变量,那么p != nil测试为真。指针之间也是可以进行相等测试的,只有当它们指向同一个变量或全部是nil时才相等

func main() {var x, y intfmt.Println(&x == &x, &x == &y, &x == nil) // "true false false"
}

字符串

窥探字符串类型

因为字符串是不可修改的,因此尝试修改字符串内部数据的操作也是被禁止的,例如:

s[0] = 'L'

在一个双引号包含的字符串中,可以用以反斜杠\开头的转义序列插入任意的数据。下面的换行、回车和制表符等是常见的ASCII控制代码的转义方式:

\a      响铃
\b      退格
\f      换页
\n      换行
\r      回车
\t      制表符
\v      垂直制表符
\'      单引号
\"      双引号
\\      反斜杠

使用反引号代替双引号,就可以定义一个多行字符串:

func main() {const GoUsage = `Go is a tool for managing Go source code.Usage:go command [arguments]
...`fmt.Println(GoUsage)
}

字符串内建函数

例如内置的len函数可以返回一个字符串中的字节数目:

func main() {s := "hello, world"fmt.Println(len(s)) // "12"d := "你好,世界"fmt.Println(len(d)) // "15"
}

常用操作:

方法介绍
len(str)求长度
+或fmt.Sprintf拼接字符串
strings.Split分割
strings.Contains判断是否包含
strings.HasPrefix,strings.HasSuffix前缀/后缀判断
strings.Index(),strings.LastIndex()子串出现的位置
strings.Join(a[]string, sep string)join操作

字符串和数字的转换

将一个整数转为字符串,一种方法是用fmt.Sprintf返回一个格式化的字符串;另一个方法是用strconv.Itoa

func main() {x := 123y := fmt.Sprintf("%d", x)fmt.Println(y, strconv.Itoa(x)) // "123 123"
}

如果要将一个字符串解析为整数,可以使用strconv包的Atoi或ParseInt函数,还有用于解析无符号整数的ParseUint函数:

func main() {x, _ := strconv.Atoi("123")y, _ := strconv.ParseInt("123", 10, 64)fmt.Println(x)fmt.Println(y)
}

http://www.ppmy.cn/devtools/116695.html

相关文章

word-break和word-wrap

1&#xff0c;word-break:break-all 例如div宽200px&#xff0c;它的内容就会到200px自动换行&#xff0c;如果该行末端有个英文单词很长&#xff08;congratulation等&#xff09;&#xff0c;它会把单词截断&#xff0c;变成该行末端为conra(congratulation的前端部分)&#…

SpringCloud Feign 以及 一个标准的微服务的制作

一个标准的微服务制作 以一个咖啡小程序项目的订单模块为例&#xff0c;这个模块必将包括&#xff1a; 各种实体类&#xff08;pojo,dto,vo....&#xff09; 控制器 controller 服务类service ...... 其中控制器中有的接口需要提供给其他微服务&#xff0c;订单模块也需要…

MySQL—触发器详解

基本介绍 触发器是与表有关的数据库对象&#xff0c;在 INSERT、UPDATE、DELETE 操作之前或之后触发并执行触发器中定义的 SQL 语句。 触发器的这种特性可以协助应用在数据库端确保数据的完整性、日志记录、数据校验等操作。 使用别名 NEW 和 OLD 来引用触发器中发生变化的记…

江科大51单片机

文章目录 led灯led点亮led闪烁流水灯 独立按键按键点灯按键消抖按键实现二进制流水灯按键实现流水灯 数码管静态数码管显示动态数码管显示 矩阵键盘定时器/中断串口通信led点阵屏DS1302实时时钟蜂鸣器AT24C02DS18B20LCD1602直流电机驱动AD/DA红外遥控 led灯 创建项目&#xff…

基于代理的分布式身份管理方案

目的是使用分布式的联合计算分发去替换掉区块链中原有的类第三方可信中心的证书机制&#xff0c;更加去中心化。 GS-TBK Group Signatures with Time-bound Keys. CS-TBK 算法 Complete subtree With Time-bound Keys&#xff0c;该算法是用来辅助检测用户的签名是否有效&…

MySQL篇(视图)(持续更新迭代)

目录 一、简介 二、语法 1. 创建 2. 查询 3. 修改 4. 删除 三、演示示例 1. 案例 2. 测试 3. 疑问 四、检查选项 1. 简介 2. 两种 2.1. CASCADED 2.2. LOCAL 五、视图的更新 1. 简介 2. 实例演示 六、视图的作用 1. 简单 2. 安全 3. 数据独立 七、演示案…

基于php的小说阅读系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpvueMySQL的小说阅读系…

java高手集锦

在入职在行业后&#xff0c;特别是这四五年内&#xff0c;本菜鸟遇到了很多行业中的大师&#xff0c;在此我想展示一下大师的代码片断&#xff0c;以及与大师的对话录。以便让有幸能读到此系列文章的人能领略大师的风范。 大师的代码&#xff1a; public void doSomeThing(){A…