Golang入门与实践————01-基础部分

5.12 Go学习笔记

1. 初识Go语言

1.1 什么是Go语言

  1. 高性能、高并发:不需要去寻找优化过的第三方库,而是利用基本库或者利用基本库封装的第三方库就可以开发高并发第三方应用程序。

  2. 语法简单、学习曲线平缓:语法语言风格类似于C语言,比如吃掉了表达式括号、循环也只有一种for循环表达式。这样直接就可以实现数值、键值的各种遍历。

package main

import (
    "net/http"
)

func main() {
    http.Handle("/", http.fileServer(http.Dir(".")))
    http.ListenAndServe(":8080",nil)
}
  1. 丰富的标准库:Go语言具有很多功能完善、性能优良的标准库,利用标准库就可以完成大部分计数功能的开发,关键在于这些标准库有很大的稳定性和兼容性保障,能够持续享受标准库迭代带来的性能优化,这极大的降低了学习和开发的难度。
  2. 完善的工具链:Go语言拥有丰富的工具链,在编译,代码提示,代码格式化,语法检查、包管理等都有对应的工具。还内置了单元测试框架,可以对每个单元单独测试。
  3. 静态编译:Go语言中所有的编译结果都是静态链接的,只需要拷贝编译之后唯一的一个编译文件就可以正确运行,比C++和Java要方便的多。
  4. 快速编译:Go语言具有静态语言几乎最快速的编译速度,在字节跳动里面的大量微服务部署小于一分钟,在本地开发中修改一条代码,也可以在一秒钟左右增量编译完成,这个速度是C++和Java开发者难以想象的。
  5. 跨平台:Go语言可以再Windows系统、Linux系统、MacOS系统下运行。除此之外Go语言还能再很多奇奇怪怪的设备上运行,比如说路由器,树莓派。还具有交叉编译能力,无序配置交叉配置环境。
  6. 垃圾回收:即在编写代码的时候不用担心其内存分配释放,可以安心专注于业务开发。

1.2 哪些公司在使用Go语言

  • ByteDance
  • Google
  • Tencent
  • Facebook

1.3 字节跳动为什么全面拥抱Go语言

  1. 最早使用的 Python,由于性能问题换成了Go。
  2. C++不太适合在线Web业务
  3. 早起团队非Java背景
  4. 性能较好
  5. 部署简单、学习成本低
  6. 内部 RPC 和 HTTP 框架的推广

2. 基础语法

2.1 第一个hello Golang文件

package main //入口包

import (
	"fmt" //导入标准库里的fmt包 主要控制字符串的格式化输入输出
)

func main() {
	fmt.Println("hello Golang!")
}

2.2 基础语法

Go语言里面变量常量的声明------------Go语言是一种强类型语言
变量举例:通过var声明变量/通过 := 来声明变量
	var a = "initial" //字符串 go语言会自动检测声明的变量的类型

	var b, c int = 1, 2//整形 通过加上类型名来指定声明的变量

	var d = true//布尔型

	var e float64//浮点型
	
	f := float32(e)//声明变量(对变量赋值)

	g := a + "fop" //在go语言中字符串可以做拼接运算
常量举例:通过 const 来声明常量

​ go里面的常量不用确定类型,他会根据上下文自动确定类型。

const s string = "constant" //字符串常量
const h = 500000 //整形数字常量
const i = 3e20 / h //常量
if - else 写法

Golang里面条件判断语句的写法和C和C++很类似,不同点为golang里面没有中括号包含条件。

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

if num := 9; num < 0 {
    fmt.Println(num, "is negative")
} else if num < 10 {
    fmt.Println(num, "has 1 digit")
} else {
    fmt.Println(num, "has multiple digits")
	}

注意:Golang不能像C或者C++一样把if语句的条件和执行语句写在同一行
Golang里面的循环

Golang语言里只有一个for循环,没有while/do while循环等。

for { //for后面什么条件都不写,则为一个死循环,作用和 while(1)一样
    fmt.Println("loop")
    break
}

for j := 7; j < 9; j++ {
    fmt.Println(j)
}
//与C和C++一样,循环判断条件三个中任意一个可以省略。

for n := 0; n < 5; n++ {
    if n%2 == 0 {
        continue //在Golang里面也可以使用continue继续循环 和 break 跳出循环
    }
    fmt.Println(n)
}

Golang里面的switch结构

Golang里面的switch结构和C和C++十分类似,唯一一个很大的不同点就是在Golang里面的switch不用加break就可以跳出分支。

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 { //这里可以不写变量名称 可以利用这点来模拟if-else嵌套
    case t.Hour() < 12:
    fmt.Println("it's brfore noon")
    default:
    fmt.Println("it's after noon")
}

Golang当中的数组
var a [5]int //定义数组
a[4] = 100 //向数组指定位置写入值
fmt.Println(a[4], len(a)) //输出对应位置中的数组的值
Golang中的切片

切片不同于数组,你可以在任意时刻更改切片的长度,同时他也拥有比数组更多难绷的处理方法,实际场景中使用的也最多。

s := make([]string, 3) //创建切片
s[0] = "a"
s[1] = "b"
s[2] = "c"
//分别给切片内容赋值
fmt.Println("get:", s[2]) // c
fmt.Println("len:", len(s)) //获取切片长度 3

s = append(s, "d")//在切切片后面追加元素
s = append(s, "e", "f")//在切片中追加元素要注意把赋值回原来的切片
fmt.Println(s) //[a b c d e f]

c := make([]srting, len(s))
copy(c, s)
fmt.Println(c) //[a b c d e f] 将切片s复制给新生成的切片c

//切片还有类似python的语法

fmt.Println(s[2:5]) //[c d e]

Golang中的map

在别的语言中,map一般被叫做哈希或者字典,在实际开发中使用最频繁的数据结构。

m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) //map[one :1, two :2]

fmr.Println(len(m)) //2
fmt.Println("one") //1

r, ok := m["unknow"] //利用 ok 语句可以查询 map 中是否具有某个元素。
fmt.Println(r, ok) //0 false

delete(m, "one") //删除map中指定的元素

//另一种定义的方法
m2 := map[string]int{"one": 1, "two": 2}
fmt.Println(m2) //注意,打印map的输出时是完全随机的!
Golang中的range

我们可以利用range来循环遍历Golang中的map和数组。

nums := []int{2, 3, 4}

sum := 0
for i, num := range nums {
    sum += num
    if num == 2 {
        fmt.Println("index:", i,"num", num) //index: 0,num:2
    }
}
fmt.Println(sum) // 9

m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
    fmt.Println(k, v) // b B a A
}

for k := range m {
    fmt.Println("key", k) //key a; key b
}
Golang中的函数

Golang中的函数传入值的类型确认是后置的,同时也支持返回多个值,一个是真正的返回结果,另一个是错误信息。

func add(a int, b int) 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 // xx true/false
}//这里就返回了一个变量和一个bool值
Golang中的指针

Golang中的指针用法没有C++那么多,最常用于修改传入函数中参数的值。

func add2(n int) {
    n += 2
}

func add2ptr(n *int) {
    *n += 2 //变量前面需要加一个*
}
//在调用时 指针传参要用&当前缀
n := 5
add2(n)
fmt.Println(n) //5
addptr(&n) 
fmt.Println(n) //7
Golang中的结构体
package main 
import "fmt"

type user struct {
    name string
    password string 
 //定义方法如上   
}

func main() {
    a := user{name: "wang", password: "1024"}
    //初始化结构体方法一
    b := user{"wang", "1024"}
    //初始化结构体方法二
    c := user{name: "Wang"}
    //也可以这样单独命名
    
    //利用点方法定义
    var d user //定义一个结构体实例对象 d
    d.name = "wang"
    d.password = "1024"
    
    fmt.Println(a, b, c, d)//........
    fmt.Println(checkPassword(a, "1023"))//false
    
    //密码检查函数
    func checkPassword(u user, password string) bool{
        return u.password == password 
    }
    
}
Golang中的结构体方法

类似于C++中结构体函数,使其变成了一个类成员函数。

package main 
import "fmt"

type user struct {
    name string
    password string  
}
func (u user) checkPassword(u user, password string) bool{
        return u.password == password 
    }//密码验证

func (u *user) resetPassword(password string) bool{
         u.password = password 
    }//密码修改

func main () {
    a := {"wang", "1024"}
    a.resetPassword("2048") //
    fmt.Println(a.checkPassword("2048"))	//true
}
Golang中的错误处理
package main 
import {
    "errors" //引入错误处理基本库
    "fmt" 
}

type user struct {
    name string
    password string
}

func findUser(users []user, name tring) (v *user, err error) {                                                             for _, u := range users {
                                                                  if u.name == name {                                             return &u, nil                                           	}                                                         }
                                                              return nil, errors New("Not found")                           }

funck main() {
    err := findUser([]user{{"wang", "1024"}}, "wang")
    if err != nil {
        fmt.Println(err)
        return 
    }
    fmt.Println(u.name) //wang
    
    if u, err := findUser([]user{{"wang", "1024"}}, "li");err != nil {
        fmt.Println(err) //Not found
    return
        {
            else {
                fmt.Println(u.name)
            }
        }
 }
Golang中的字符串操作
a := "hello"

fmt.PrintIn(strings.Contains(a, "ll"))//true
fmt.Println(strings.Count(a,"l"))//2 字符出现次数
fmt.PrintIn(strings.HasPrefix(a,"he"))// true
fmt.Println(strings.HasSuffix(a,"llo"))// true
fmt.PrintIn(strings.Index(a,"l"))// 2 字符出现索引
fmt.Println(strings.Join([]string("he""llo"},"-"))//he-llo
fmt .PrintIn(strings.Repeat(a,2)) //hellohello 重复两次
fmt.PrintIn(strings.Replace(a,"e","E"-1)) //hEllo 更改
fmt.Println(strings.Split( "a-b-c","-")) //[a,b,c]剔除对应符号
fmt.PrintIn( strings.ToLower(a))//hello 转成小写
fmt.PrintIn( strings.ToUpper(a))//HELLO 转成大写
fmt.PrintIn(len(a))//5 打印字符串长度 
b:="你好"
fmt.PrintIn(len(b)) //6 注意如果字符串是中文时,一个汉字可能对应多个字符
Golang中的字符串格式化
type point strucy{
    x, y int
}
func main() {
    s := "hello"
    n := 123
    p := pointg{1, 2}
    fmt.Println(s, n)//hello 123
    fmt.Println(p) //{1 2}
    //这是第一种常用的打印方法 直接打印出变量内容 且末尾换行
    
    fmt.Printf("s=%v\n", s)//s=hello
    fmt.Printf("n=%v\n", n)//n=123
    fmt.Printf("p=%v\n", s)//p={1 2}
    fmt.Printf("p=%v+\n", p)//p={x:1 y:2} //打印的信息更详细
    fmt.Printf("p=%+#v\n", p)//p=main.point{x:1, y:2}
    
    f:= 3.141592653
    fmt.Println(f) //3.141592653
    fmt.Println("%2f\n", f) //3.14 取两位小数
}
Golang中JSON处理
package main

import {
    "emcoding/json"
    "fmt"
}

type unserInfo struct {
    Name string
    Age int `json: "age"`//在这里加json使得输出时Age大写变小写age 
    Hobby []string
}

func main() {
    a := userInfo{Name: "wang", Age: 18, Hobby:      	[]string{"Goalng", "Typestript"}}
    buf, err := json.Marshal(a)
    if err != ni; {
        panic(err)
    }
    fmt.Println(buf) //[123 34 78 997]
    //序列化之后如果不类型转换则会打印出来16进制的编码
    fmt.Println(string(buf))//{"Name": "wang", "Age": 18, "Hobby":["Goalng", "Typescript"]}    
    
}	
Golang中的时间处理
now := time.Now() //获取当前时间

fmt.Println(now) //2022-03-27 18:04:59.433297 +0800 CST m+=0.000087933
t := time.Date(2022,3,27,1,25,36,0,time.UTC)
t2 := time.Date(2022,3,27,2,30,36,0,.time.UTC)

fmt.Priontln(t)//2022-03-27 01:25:36 +0000 UTC

fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())//2022 March 27 1 25  

fmt.Printin(t.Format("2006-01-02 15:04:05"))// 2022-03-27 01:25:36

diff := t2.Sub(t) //二者时间差

fmt.PrintIn(diff) //1h5m0s 转换为小时

fmt.Println(diff.Minutes( ),diff.Seconds( )) // 65 3900 转换为分钟和秒

fmt.Println(now.Unix())//10407300 获取时间戳
Golang中的数字解析

要引入 strconv 这个库

//用ParseFloat ParseInt解析字符串
f,_ := strconv.ParseFloat("1.234"64) //返回一个64位精度的浮点数
fmt.PrintIn(f) // 1.234
n,_ := strconv.ParseInt("111"1064) // 目标字符串 返回进制 返回数精度值
fmt.Printin(n) // I11

n,_ = strconv.ParseInt("0x1000"064) //转为64位精度的整数
fmt.Println(n) // 4096
n2 _ := strconv.Atoi("123")  //快速的把十进制数字字符串转为数字
fmt.PrintIn(n2) // 123
n2,err := strconv.Atoi("AAA")
fmt,Println(n2,err) // 0 strconv.Atoi: parsing "AAA": invalid syntax  err回调函数报错: 字符串不是数字字符串
Golang中的进程查询
package main
import {
    "fmt!"
    "os"
	"exec"
}
func main() {
    // go run example/20-env/main.go a b c d
    fmt.Println(os.Args )
    //[/var/folders/8p/n34xxfnx38dg8bv_x8162t_m0000gn/T/go-		build3406981276/b001/exe/main a b cd]
    fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
    fmt.Println( os .Setenv("AA""BB"))
buf,err := exec.Command("grep","127.0.0.1","/etc/hosts").CombinedOutput()
    if err != nil {
        panic(err)
    }
fmt.Printin(string(buf)) // 127.0.0.1  localhost
    }

进程查询

package main
import {
    "fmt!"
    "os"
	"exec"
}
func main() {
    // go run example/20-env/main.go a b c d
    fmt.Println(os.Args )
    //[/var/folders/8p/n34xxfnx38dg8bv_x8162t_m0000gn/T/go-		build3406981276/b001/exe/main a b cd]
    fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
    fmt.Println( os .Setenv("AA""BB"))
buf,err := exec.Command("grep","127.0.0.1","/etc/hosts").CombinedOutput()
    if err != nil {
        panic(err)
    }
fmt.Printin(string(buf)) // 127.0.0.1  localhost
    }

总结:

此次博主分享了关于Go语言的发展历史以及20种基本语法,并且给出了具体代码举例,下一篇Go语言内容博主会更新一个关于Go语言的小实践项目,感兴趣的朋友们可以关注博主防止走丢哦~

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不懂it的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值