
寫在前面
竟然大半夜不睡覺寫博客,這個標題,是不是像一些無良賣課吸睛公眾號,點開一看味同嚼蠟,
好吧,大半夜碼字,因為實在激動,從下午六點多開始學習golang,花了三個小時了解變數、指標、資料型別、結構體、語法、函式以及golang的切片、管道、(go程)協程等特性,用半小時思考我該寫個啥,花了一個半小時寫了個小白入門爬蟲,最后傻樂了半小時,
文章目錄
- 寫在前面
- 前言
- 一、Golang是什么?
- 1.簡介
- 二、使用步驟
- 1.下載鏡像
- 2.下載GoLang(別的也行,VSCode)
- 3.開干
- 三、核心特性
- 1.goroutine協程
- 1.1 什么是 Go 協程?
- 1.2 goroutine和執行緒的比較
- 1.3 goroutine協程實作原理
- 2.channel
- 2.1 什么是 channel?
- 2.2 咋用?
- 四、小小爬蟲
- 1.爬蟲四步
- 2.代碼
- 3.結果
- 總結
前言
我是寫Java的,所以本文是淺嘗輒止golang后一得之見,才疏學淺,希望對想了解golang的小伙伴有所幫助,一、Golang是什么?
1.簡介
官話:golang是Google開發的一種 靜態強型別、編譯型,并發型,并具有垃圾回收功能的編程語言,
個人看法:
- 有很多C語言的影子,比如語法、控制流結構、基礎資料型別、傳參、指標等,方便上手(Java寫習慣了,順手扔出來的分號,是那么的格格不入無處安放)
- 能訪問底層作業系統,還提供了強大的網路編程和并發編程支持(channel和Goroutine是核心)
二、使用步驟
1.下載鏡像

鏡像地址
下載對應的版本就行
2.下載GoLang(別的也行,VSCode)
鏈接在此
3.開干
個人途徑
- 官方檔案:檔案一號,檔案二號
- 視頻:視頻在此
三、核心特性
1.goroutine協程
大道至簡
1.1 什么是 Go 協程?
先理解行程、執行緒 之間概念的區別
對于 行程、執行緒,都是有內核進行調度,有 CPU 時間片的概念,進行 搶占式調度(有多種調度演算法)
- 協程是用戶級執行緒,對內核是透明的,系統并不知道有協程的存在,
- 完全由用戶自己的程式進行調度,通常只能進行協作式調度,需要協程自己主動把控制權轉讓出去之后,其他協程才能被執行到,
goroutine 和協程區別
- 本質上,goroutine 就是協程, 不同的是,Golang 在 runtime、系統呼叫等多方面對 goroutine調度進行了封裝和處理,當遇到長時間執行或者進行系統呼叫時,會主動把當前 goroutine 的CPU 轉讓出去,讓其他goroutine 能被調度并執行,
- 從語言層面原生支持協程,在函式或者方法前面加 go關鍵字就可創建一個協程,
1.2 goroutine和執行緒的比較
| 記憶體消耗 | 切換調度開銷 |
|---|---|
| 每個 goroutine (協程) 默認占用記憶體遠比 Java 、C 的執行緒少,goroutine:2KB 執行緒:8MB | goroutine 遠比執行緒小;執行緒:涉及模式切換(從用戶態切換到內核態)、16個暫存器、PC、SP…等暫存器的重繪等,goroutine:只有三個暫存器的值修改 - PC / SP / DX. |
1.3 goroutine協程實作原理
協程是基于執行緒的,內部實作上,維護了一組資料結構和 n 個執行緒,真正的執行還是執行緒,協程執行的代碼被扔進一個待執行佇列中,由這 n 個執行緒從佇列中拉出來執行,這就解決了協程的執行問題,
暫時只了解到這里,待續
2.channel
2.1 什么是 channel?
channel是Go語言中各個并發結構體(goroutine)之前的通信機制, 通俗的講,就是各個goroutine之間通信的”管道“,有點類似于Linux中的管道,
2.2 咋用?
1.宣告channel
2.參考型別
3.單向channel
var 變數名 chan 資料型別
channel和和map類似,channel也一個對應make創建的底層資料結構的參考,
當我們復制一個channel或用于函式引數傳遞時,我們只是拷貝了一個channel參考,因此呼叫者和被呼叫者將參考同一個channel物件,和其它的參考型別一樣,channel的零值也是nil,定義一個channel時,也需要定義發送到channel的值的型別,
// 方法一:channel的創建賦值
var ch chan int;
ch = make(chan int);
// 方法二:短寫法
ch:=make(chan int);
// 方法三:綜合寫法:全域寫法!!!!
var ch = make(chan int);
單向chan
//定義只讀的channel
read_only := make (<-chan int)
//定義只寫的channel
write_only := make (chan<- int)
四、小小爬蟲
1.爬蟲四步
- 踩點(找目標)http://www.netbian.com/fengjing/index_2.htm
- 爬(拿資料)
- 過濾(獲取想要的)
- 資料處理
2.代碼
package main
import (
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"strings"
"sync"
"time"
)
var (
//存放圖片的管道
chanImageUrls chan string
wg sync.WaitGroup
//監控協程
chanTask chan string
)
func main() {
chanImageUrls = make(chan string, 1000000)
chanTask = make(chan string, 26)
for i := 2; i < 10; i++ {
wg.Add(1)
go getImageUrls("http://www.netbian.com/fengjing/index_" + strconv.Itoa(i) + ".htm")
}
wg.Add(1)
go checkOK()
//下載
for i := 0; i < 3; i++ {
wg.Add(1)
go downloadImg()
}
wg.Wait()
}
//下載檔案
func downLoadFile(url string, filename string) (ok bool) {
resp, err := http.Get(url)
HandleError(err, "http.get.url")
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
HandleError(err, "res.Body")
filename = "D:/test/" + filename
err = ioutil.WriteFile(filename, bytes, 0666)
if err != nil {
return false
} else {
return true
}
}
//下載圖片
func downloadImg() {
for url := range chanImageUrls {
filename := getFilenameFromUrl(url)
ok := downLoadFile(url, filename)
if ok {
fmt.Println(filename + "下載成功")
} else {
fmt.Println(filename + "下載失敗")
}
}
}
//截取名字
func getFilenameFromUrl(url string) (filename string) {
lastIndex := strings.LastIndex(url, "/")
filename = url[lastIndex+1:]
timePrefix := strconv.Itoa(int(time.Now().UnixNano()))
filename = timePrefix + "_" + filename
return
}
//任務統計協程
func checkOK() {
var count int
for {
url := <-chanTask
fmt.Println("完成爬取 " + url)
count++
if count == 26 {
close(chanImageUrls)
break
}
}
wg.Done()
}
//爬取圖片鏈接到管道
func getImageUrls(url string) {
urls := getImages(url)
for _, url := range urls {
chanImageUrls <- url
}
chanTask <- url
wg.Done()
}
//獲取當前頁面圖片鏈接
func getImages(url string) (urls []string) {
pageStr := getResByPage(url)
re := regexp.MustCompile(reImage)
result := re.FindAllStringSubmatch(pageStr, -1)
for _, res := range result {
url := res[0]
urls = append(urls, url)
}
return urls
}
3.結果




總結
睡覺
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/158501.html
標籤:其他
上一篇:Raft 協議原理詳解
下一篇:攜手分布式存盤 助力智慧城市建設
