【Go】Go语言学习笔记--Go语言基础【上】

简介: 变量标准声明

变量和常量

变量

标准声明

var 变量名 变量类型
复制代码

举个栗子🌰

var age int
var name string
var isOk bool
复制代码

批量声明

var (
    变量名 类型
    变量名 类型
    变量名 类型
)
复制代码

举个栗子🌰

var (
    age int
    name string
    isOk bool
)
复制代码

变量的初始化

Go语言声明变量的时候,每个变量其实会被初始化成该类型的默认值。

  1. 整型和浮点型变量为 0
  2. 字符串变量为 空字符串
  3. 布尔型变量为 false
  4. 切片、函数、指针变量默认为 nil声明并指定初始值的标准格式:
var 变量名 类型 = 表达式
复制代码

举个栗子🌰

var name string = "张三"
var age int = 18
var isOk bool = true
复制代码

或者还可以这样

var name, age, isOk = "张三", 12, true
复制代码

类型推导

有时候可以选择性省略变量的类型,编译器会根据等号右边的值来推导变量的类型来完成初始化。

举个栗子🌰

var name = "张三"
var age = 12
var isOk = true
复制代码

短变量声明

函数内部,还可以用:=方式声明并完成变量的初始化。

举个栗子🌰

package main
import "fmt"
var m = 100 // 全局声明变量m
func main() {
    n := 10
    m := 200 // 局部声明变量m
    fmt.Println(m,n)
}
复制代码

匿名变量

多重赋值,忽略某个值,匿名变量用_表示。匿名变量不会占用命名空间,不会分配内存。

举个栗子🌰

func foo() (int, string) {
    return 12, "张三"
}
func main() {
    age,_ := foo()
    _,name := foo()
    fmt.Println(name, age)
}
复制代码

注意事项

  1. 函数外的每个语句都必须以关键字开始(var、const、func等)
  2. := 不能在函数外使用
  3. _多用于占位,表示忽略

常量

Go中的常量与JavaScript中对常量的定义相似,指的是恒定不变的值,都是用const声明,有一点不同是,Go中的常量在定义的时候必须赋值。

const HOME_ADDRESS = "我滴家在东北~松花江上昂昂"
const MY_GENDER = "男"
复制代码

多个常量可以一起声明:

const (
    HOME_ADDRESS = "我滴家在东北~松花江上昂昂"
    MY_GENDER = "男"
)
复制代码

const同时声明常量的时候,如果省略了值,则表示和上面一行的值相同:

const (
    HOME_ADDRESS = "我滴家在东北~松花江上昂昂"
    HIS_HOME_ADDRESS
    MY_GENDER = "男"
    HIS_GENDER
)
复制代码

HIS_HOME_ADDRESS 值为 我滴家在东北~松花江上昂昂HIS_GENDER 值为

iota

常量计数器,JavaScript中没有。

iota只能在常量的表达式中使用,变量不行的!

iota 在const关键字出现的时候立马被重置为0。const中每新增一行常量声明,将会使iota计数一次(可理解为0~正无穷 const语句块中的索引)。

举个栗子🌰

const (
    n1 = iota
    n2
    n3
    n4
    n5
)
fmt.Println(n1,n2,n3,n4,n5) // 0 1 2 3 4
复制代码

常见的iota示例

使用_跳过某些值

const (
    n1 = iota
    _
    n2
    _
    n3
    n4
)
fmt.Println(n1,n3,n4,n5) // 0 2 4 5
复制代码

iota声明中 插队操作

const (
   n1 = iota //0
   n2 = 1000 // 1000
   n3
   n4 = 9999 // 9999
   n5 = iota // 4
   n6 // 5
)
const n7 = iota
fmt.Println(n1,n2,n3,n4,n5,n6,n7)
复制代码

基于李文周的示例改造了一点儿,结构发现n3算错了(以为是iota的值,也就是索引),n3在const声明块中因为没有被赋值,所以和他上面的值相同,也就是1000,直到n5重新赋值iotan6没有赋值,等于n5,也就是等于iotaiota自增为6,n7重新遇到const关键字,iota重置为0

数据类型

整型

浮点型

复数

布尔值

字符串

字符串转义

转义符 含义
\r 回车符(返回首行)
\b 换行符(直接调到下一行的同列位置)
\t 制表符
' 单引号
" 双引号
\ 反斜杠

举个栗子🌰

package main 
import "fmt"
func main() {
    fmt.Println("str := \"c:\\code\\day01\\main.go")
}
复制代码

多行字符串

定义多行字符串的时候,用反引号

s1 := `第一行
第二行
第三行
`
复制代码

字符串常用操作

方法 介绍
len(str) 求长度
+ 拼接字符串
strings.Split 分割
strings.Contains 是否包含
strings.HasPrefix, strings.HasSuffix 前缀,后缀判断
strings.Index(), strings.LastIndex 子串出现的位置,下标,索引
strings.join join操作

举个栗子🌰

// ----------- len ------------
s1 := "abcd"
fmt.Println(len(s1)) // 4
// ----------- + ------------
s1 := "ab"
s2 := "cd"
s3 := s1 + s2
fmt.Println(s3) // abcd
// ----------- strings.Split ------------
参数1:待分割的字符串
参数2:分割符
返回值:返回一个字符串切片
s1 := "u&me&she&he"
s1_slice := strings.split(s1, "&")
fmt.Println("result:", s1_slice) // [u me she he]
fmt.Println("len:", len(s1_slice)) // 4
fmt.Println("cap:", cap(s1_slice)) // 4
注意事项:
    1. 字符串中不包含分隔符时,将原字符串转换成一个len&cap为1的字符串切片。 // [ u&me&she&he ] len:1 cap:1
    2. 当分隔符是空字符串时,将每个字符切割成一个单独的元素。//[u & m e & s h e & h e] len:1 cap:1
// ----------- strings.Contains ------------
s1 := "u&me&he&she"
s2 := "me"
s3 := "haha"
fmt.Println(strings.Contains(s1, s2)) // true
fmt.Println(strings.Contains(s1, s3)) // false
// ----------- strings.HasPrefix, HasSuffix ------------
参数1:待检测的字符串
参数2:指定的前缀/后缀
返回值:返回一个布尔值
s1 := "goodday.png"
fmt.Println(strings.HasPrefix(s1, "goodday")) // true
fmt.Println(strings.HasPrefix(s1, "goodday")) // true
fmt.Println(strings.HasSuffix(s1, "png")) // true
fmt.Println(strings.HasSuffix(s1, "jpg")) // false
// ----------- strings.Index, LastIndex ------------
s1 := "abcd"
fmt.Println(strings.Index(s1, "a")) // 0
fmt.Println(strings.Index(s1, "b")) // 3
fmt.Println(strings.Index(s1, "e")) // -1
// ----------- strings.Join ------------
s := []string{"11", "12", "13"}
res := strings.Join(s, "|")
fmt.Println(res) // 11|12|13
复制代码

byte和rune类型

Go语言的字符有两种:

  1. byte,代表ASCII码的一个字符
  2. rune,代表一个UTF-8字符 处理复合字符时,需要用rune类型
    Go语言的字符串底层是一个byte数组,中文字符在utf-8下占3个字节,Go的默认编码是utf-8。
s := "hello啊!树哥"
for i := 0; i < len(s); i++ {
    fmt.Println("%v(%c)", s[i], s[i])
}
fmt.Println()
for _, r := range s{
   fmt.Printf("%v(%c)", r, r)
}
复制代码

获取字符串的长度

如果想拿到一个字符串的真实长度,可以通过一下两种办法:

fmt.Println(len([]rune(s))) //9
fmt.Println(len(utf8.RuneCountInString(s))) // 9
复制代码

修改字符串

要修改字符串,首先将其转化为rune或者byte,修改完成之后再转换成string,无论哪种转换,都会重新分配内存,并复制字节数组。

s1 := "helloa!shugge!"
byteS1 := []byte(s1)
byteS1[0] = 'w'
fmt.Println(string(byteS1)) // welloa!shugge!
s2 := "hello啊!树哥!"
runeS2 := []rune(s2)
runeS2[7] = '涛'
fmt.Println(string(runeS2)) // hello啊!涛哥!
复制代码

字符串的操作这里与JavaScript大相径庭,在JavaScript字符串的修改是可以任意修改的,而且单个字符可以用''也可以用"",也没有对不同字符类型的特殊处理这一步。

关于字符编码

程序中所有的信息都是通过二进制的形式存储在计算机底层的,将字符转换成二进制的过程叫做编码,将二进制转化成字符的过程叫做解码字符集相当于一个枚举映射表。

  1. ASCII码:早期计算机应用在欧洲等发达国家,所以这个字符集只存在拉丁字母和阿拉伯数字。
  2. 非ASCII码, 因为ASCII码不能完整表示其他国家语言,所以各个国家都基于ASCII码做了拓展,比如我国的GB 类的字符集GB2312GBK,但是问题出现了,国与国之间谁也不懂谁的编码,于是有了Unicode
  3. Unicode:延伸出了UTF-32UTF-16UTF-8

类型转换

Go语言中只有强制类型转换,没有隐式类型转换。

强制类型转换的基本语法如下:

T(表达式)
复制代码

T代表的要转换的类型。表达式包括变量、复杂算子和函数返回值等等。

数据类型练习题

  1. 编写代码分别定义一个整型、浮点型、布尔型、字符串型变量,使用fmt.Printf()搭配%T分别打印出上述变量的值和类型。
s := "hello树先生"
n := 12
b := true
f := 3.1415
fmt.Printf("%v:%T", n,n)
fmt.Println()
fmt.Printf("%v:%T", b,b)
fmt.Println()
fmt.Printf("%v:%T", f,f)
fmt.Println()
fmt.Printf("%v:%T", s,s)
还有两种获取变量和类型的方法
1. reflect.Typeof(s)
2. reflect.Typeof(s).Name()
关于Printf
1.%T 打印变量的类型
2.%v 以默认的方式打印变量的值
复制代码
  1. 编写代码统计出字符串"hello!树先生!"中汉字的数量。
// 我的解法,因为Go默认使用 UTF-8解码,所以一个中文字符是3
str := "hello!树先生!"
runeStr := []rune(str)
count := 0
for _, r := range runeStr {
   if len(string(r)) >= 3 {
      count++
   }
}
fmt.Printf("str中汉字有%v个", count)
// 一个好的解法
// unicode 包提供了一些测试Unicode码点属性的数据和函数.
// Is 返回该符文是否在指定范围的表中。
// Han 汉字的表范围
str := "hello!树先生!"
count := 0
for _,item := range str {
   if unicode.Is(unicode.Han, item) {
      count++
   }
}
fmt.Printf("str中汉字有%v个", count)


目录
相关文章
|
20小时前
|
JSON 安全 Java
2024年的选择:为什么Go可能是理想的后端语言
【4月更文挑战第27天】Go语言在2024年成为后端开发的热门选择,其简洁设计、内置并发原语和强大工具链备受青睐。文章探讨了Go的设计哲学,如静态类型、垃圾回收和CSP并发模型,并介绍了使用Gin和Echo框架构建Web服务。Go的并发通过goroutines和channels实现,静态类型确保代码稳定性和安全性,快速编译速度利于迭代。Go广泛应用在云计算、微服务等领域,拥有丰富的生态系统和活跃社区,适合作为应对未来技术趋势的语言。
8 0
|
22小时前
|
Go 开发者
Golang深入浅出之-Go语言项目构建工具:Makefile与go build
【4月更文挑战第27天】本文探讨了Go语言项目的构建方法,包括`go build`基本命令行工具和更灵活的`Makefile`自动化脚本。`go build`适合简单项目,能直接编译Go源码,但依赖管理可能混乱。通过设置`GOOS`和`GOARCH`可进行跨平台编译。`Makefile`适用于复杂构建流程,能定义多步骤任务,但编写较复杂。在选择构建方式时,应根据项目需求权衡,从`go build`起步,逐渐过渡到Makefile以实现更高效自动化。
9 2
|
22小时前
|
存储 Go
Golang深入浅出之-Go语言依赖管理:GOPATH与Go Modules
【4月更文挑战第27天】Go语言依赖管理从`GOPATH`进化到Go Modules。`GOPATH`时代,项目结构混乱,可通过设置多个工作空间管理。Go Modules自Go 1.11起提供更现代的管理方式,通过`go.mod`文件控制依赖。常见问题包括忘记更新`go.mod`、处理本地依赖和模块私有化,可使用`go mod tidy`、`replace`语句和`go mod vendor`解决。理解并掌握Go Modules对现代Go开发至关重要。
7 2
|
22小时前
|
安全 测试技术 Go
Golang深入浅出之-Go语言单元测试与基准测试:testing包详解
【4月更文挑战第27天】Go语言的`testing`包是单元测试和基准测试的核心,简化了测试流程并鼓励编写高质量测试代码。本文介绍了测试文件命名规范、常用断言方法,以及如何进行基准测试。同时,讨论了测试中常见的问题,如状态干扰、并发同步、依赖外部服务和测试覆盖率低,并提出了相应的避免策略,包括使用`t.Cleanup`、`t.Parallel()`、模拟对象和检查覆盖率。良好的测试实践能提升代码质量和项目稳定性。
6 1
|
22小时前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
8 1
|
22小时前
|
安全 Go
Golang深入浅出之-Go语言标准库中的文件读写:io/ioutil包
【4月更文挑战第27天】Go语言的`io/ioutil`包提供简单文件读写,适合小文件操作。本文聚焦`ReadFile`和`WriteFile`函数,讨论错误处理、文件权限、大文件处理和编码问题。避免错误的关键在于检查错误、设置合适权限、采用流式读写及处理编码。遵循这些最佳实践能提升代码稳定性。
5 0
|
1天前
|
Go C++
go 语言回调函数和闭包
go 语言回调函数和闭包
|
1天前
|
存储 负载均衡 监控
【Go 语言专栏】构建高可靠性的 Go 语言服务架构
【4月更文挑战第30天】本文探讨了如何利用Go语言构建高可靠性的服务架构。Go语言凭借其高效、简洁和并发性能,在构建服务架构中备受青睐。关键要素包括负载均衡、容错机制、监控预警、数据存储和服务治理。文章详细阐述了实现这些要素的具体步骤,通过实际案例分析和应对挑战的策略,强调了Go语言在构建稳定服务中的作用,旨在为开发者提供指导。
|
1天前
|
测试技术 Go 开发工具
【Go语言专栏】Go语言中的代码审查与最佳实践
【4月更文挑战第30天】Go语言因其简洁、高性能及并发能力,在云计算等领域广泛应用。代码审查对提升Go代码质量、遵循规范及团队协作至关重要。审查流程包括提交、审查、反馈、修改和合并代码。工具如GoLand、Git、ReviewBoard和GitHub提供支持。最佳实践包括遵循命名规范、添加注释、保持代码结构清晰、复用代码和确保测试覆盖。积极参与代码审查是提高质量的关键。
|
1天前
|
Prometheus 监控 Cloud Native
【Go语言专栏】Go语言中的日志记录与监控
【4月更文挑战第30天】Go语言在软件开发和运维中扮演重要角色,提供灵活的日志记录机制和与多种监控工具的集成。内置`log`包支持基本日志记录,而第三方库如`zap`、`zerolog`和`logrus`则扩展了更多功能。监控方面,Go应用可与Prometheus、Grafana、Jaeger等工具配合,实现系统指标收集、可视化和分布式追踪。健康检查通过HTTP端点确保服务可用性。结合日志和监控,能有效提升Go应用的稳定性和性能。