社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
第1章 Go语言简单介绍
Go语言的设计初衷
1.针对其他语言的痛点进行设计;2.并加入并发编程;3.为大数据、微服务、并发而生的通用编程语言。
Go语言与转型
项目转型首选语言;软件工程师转型、添加技术栈的首选语言;这是一门为转型量身定制的课程。
Go语言很特别:1.没有“对象”,没有继承多态,没有泛型,没有try/catch。2.有接口,函数式编程,CSP并发模型(goroutine+channel)。
示例 语法部分:每个小片段解决实际问题
综合部分:经典算法+典型例题+微型项目
实战项目部分:搭建分布式爬虫,结构复杂
基本语法:变量;选择,循环;指针,数组,容器
面向接口编程:结构体;duck typing的概念;组合的思想
函数式编程:闭包的概念;多样的例题
工程化:资源管理,错误处理;测试和文档;性能调优
并发编程:gorountine和channel;理解调度器;多样的例题
实战项目:从0开始,使用Go语言自主搭建简单分布式爬虫。爬取相亲网站资料;
Go语言的安装与开发环境
下载Go安装包:https://studygolang.com/dl
开发环境:idea + go插件
第2章 基本语法
2-1 变量定义
使用var关键字
var a, b, c bool
var s1, s2 string = "hello, "world"
可放在函数内,或直接放在包内
使用var()集中定义变量
让编译器自动决定类型
var a, b, i, s1, s2 = true,false, 3, "hello", "world"
使用:=定义变量,只能在函数内使用
a, b, i, s1, s2 := true, false, 3, "hello', "world"
package main
import "fmt"
//函数外定义变量,不是全局变量,是包内变量
var (
aa = 3
ss = "kkk"
bb = true
)
//函数里定义变量
func variableZerovalue() {
var a int
var s string
fmt.Printf("%d %qn", a,s)
}
//变量赋初值
func variableInitialvalue() {
var a, b int = 3, 4
var s string = "abc"
fmt.Println(a, b, s)
}
func variableTypeDeduction() {
var a, b, c, s = 3, 4, true, "def"
fmt.Println(a, b, c, s)
}
func variableShorter() {
a, b, c, s := 3, 4, true, "def"
b = 5
fmt.Println(a, b, c, s)
}
func main() {
fmt.Println("Hello,World!")
variableZerovalue()
variableInitialvalue()
variableShorter()
fmt.Println(aa, ss, bb)
}
内建变量类型
bool, string
(u)int, (u)int8,(u)int16,(u)int32,(u)int64,uintptr
byte字节类型,rune字符类型32位
float32, float64,complex64实部虚部32位,complex128实部虚部64位
package main
import fmt
func euler() {
//c := 3 + 4i
//fmt.Println(complx.Abs(c))
//fmt.Println(
// cmplx.Pow(math.E, 1i * math.Pi) + 1)
fmt.Printf("%.3fn",
cmplx.Exp(1i * math.Pi) + 1)
}
func main() {
euler()
}
强制类型转换
类型转换是强制的
var a, b int = 3, 4
package main
import fmt
func triangle() {
var a, b int 3, in
var c int
c = int(math.Sqrt(float64(a * a + b * b)))
fmt.Println(c)
}
func main() {
triangle()
}
2-3 常量与枚举
常量的定义
const filename = “abc.txt”
const数值可作为各种类型使用
const a, b = 4
var c int = int(math.Sqrt(a*a + b*b))
使用常量定义枚举类型
普通枚举类型
自增值枚举类型
package main
import (
"fmt"
"math"
)
//常量定义包内,所有函数都能用。
//const filename = "abc.txt"
func consts() {
const (
filename = "abc.txt"
a, b = 3, 4
)
var c int
c = int(math.Sqrt(a*a + b*b))
fmt.Println(filename, c)
}
func enums() {
const (
cpp = iota
_
python
golang
javascrip
)
//b, kb, mb, gb, tb, pb
const (
//iota作为自增值的种子
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
fmt.Println(cpp, javascrip, python, golang)
fmt.Println(b, kb, mb, gb, tb, pb)
}
func main(){
consts()
enums()
}
变量定义要点回顾
变量类型写在变量名之后
编译器可推测变量类型
没有char,只有rune、
原生支持复数类型
2-4 条件语句
if
if的条件里不需要括号
func bounded(v int) int {
if v > 100 {
return 100
} else if v < 0 {
return 0
} else {
return v
}
}
if的条件里可以赋值
if的条件里赋值的变量作用域就在这个if语句里
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%sn", contents)
}
package main
import (
"io/ioutil"
"fmt"
)
func main() {
const filename = "abc.txt"
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%sn", contents)
}
/* if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%sn", contents)
}*/
}
switch
switch会自动break,除非使用fallthrough
switch后可以没有表达式
func eval(a, b int, op string) int {
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
case "*":
result = a * b
case "/":
result = a / b
default:
//panic报错
panic("unsupported operator:" + op)
}
return result
}
package main
import (
"io/ioutil"
"fmt"
)
func grade(score int) string {
g := ""
switch {
case score < 0 || score > 100:
panic(fmt.Sprintf(
"Wrong score: %d", score))
case score < 60:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
}
return g
}
func main() {
fmt.Println(
grade(0),
grade(59),
grade(60),
grade(82),
grade(99),
grade(100),
grade(103),
)
}
2-5 循环
for
sum := 0
for i := 1; i <= 100; i++ {
sum += 1
}
for的条件里不需要括号
for的条件里可以省略初始条件,结束条件,递增表达式
package main
import (
"fmt"
"strconv"
"os"
"bufio"
)
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
func printFile(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
//死循环
func forever() {
for {
fmt.Println("abc")
}
}
func main() {
fmt.Println(
convertToBin(5), //101
convertToBin(13), //1101
convertToBin(72337885), //
convertToBin(0), //
)
printFile("abc.txt")
forever()
}
省略初始条件,相等于while
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
省略初始条件,相等于while
for scanner.Scan() {
fmt.Println(scanner.Text())
}
无限循环
for {
fmt.Println("abc")
}
基本语法要点回顾:
for, if后面的条件没有括号
if条件里也可以定义变量
没有while
switch不需要break,也可以直接switch多个条件
2-6 函数
函数
func eval(a, b int, op string) int
函数可返回多个值:
func div(a, b int) (int, int) {
return a / b, a % b
}
函数返回多个值时可以起名字
仅用于非常简单的函数
对于调用者而言没有区别
func div(a, b int) (q, r int) {
q = a / b
r = a % b
return
}
package main
import (
"fmt"
"reflect"
"runtime"
"math"
)
func eval(a, b int, op string) (int, error) {
switch op {
case "+":
return a + b, nil
case "-":
return a - b, nil
case "*":
return a * b, nil
case "/":
q, _ := div(a, b)
return q, nil
default:
return 0, fmt.Errorf(
"unsupported operation: %s", op)
}
}
// 13 / 3 = 4 ... 1
func div(a, b int) (q, r int) {
return a / b, a % b
}
//函数式编程
func apply(op func(int, int) int, a, b int) int {
p := reflect.ValueOf(op).Pointer()
opName := runtime.FuncForPC(p).Name()
fmt.Printf("Calling function %s with args " +
"(%d, %d)n", opName, a, b)
return op(a, b)
}
/*func pow(a, b int) int {
return int(math.Pow(float64(a), float64(b)))
}*/
//可变参数列表
func sum(numbers ...int) int {
s := 0
for i := range numbers {
s += numbers[i]
}
return s
}
func main() {
if result, err := eval(3, 4, "x"); err!= nil{
fmt.Println("Error:", err)
} else {
fmt.Println(result)
}
q, r := div(13, 3)
fmt.Println(q, r)
fmt.Println(apply(
func(a int, b int) int {
return int(math.Pow(
float64(a), float64(b)))
}, 3, 4))
fmt.Println(sum(1, 2, 3, 4, 5))
}
函数式参数也可以是一个函数,也可以写一个匿名函数来调它。
函数作为参数:
func apply(op func(int, int) int, a, b int) int {
fmt.Printf("Calling function %s with %d, %dn",
runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name(),
a, b)
return op(a, b)
}
可变参数列表:
func sumArgs(values ...int) int {
s := 0
for i := range values{
sum += values[i]
}
return sum
}
函数语法要点回顾:
返回值类型写在最后面
可返回多个值
函数作为参数
没有默认参数,可选参数
2-7 指针
指针不能运算
var a int = 2
var pa *int = &a
*pa = 3
fmt.Println(a)
参数传递
Go语言只有值传递一种方式
拷贝一份a的地址,使用指针传递相当于引用传递的效果
Go语言中Object类型的名字叫Cache
package main
import (
"fmt"
)
func swap(a, b int) (int, int){
return b, a
}
func main() {
a, b := 3, 4
a, b = swap(a, b)
fmt.Println(a, b)
}
第3章 内建容器
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!