中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

做網(wǎng)站開發(fā)的女生多嗎百度推廣競(jìng)價(jià)是什么意思

做網(wǎng)站開發(fā)的女生多嗎,百度推廣競(jìng)價(jià)是什么意思,網(wǎng)站建設(shè)推廣哪里好,如何用自己的電腦做網(wǎng)站服務(wù)器目錄 一、單元測(cè)試 單元測(cè)試 子測(cè)試 TestMain 二、反射 類型判斷 通過反射獲取值 通過反射修改值 結(jié)構(gòu)體反射 利用tag修改結(jié)構(gòu)體的某些值 調(diào)用結(jié)構(gòu)體方法 orm的一個(gè)小案例 對(duì)反射的一些建議 三、網(wǎng)絡(luò)編程 socket編程 websocket編程 四、部署 打包命令 交叉編譯…

目錄

一、單元測(cè)試

單元測(cè)試?

?子測(cè)試

?TestMain

二、反射

類型判斷

通過反射獲取值

通過反射修改值

結(jié)構(gòu)體反射

利用tag修改結(jié)構(gòu)體的某些值

調(diào)用結(jié)構(gòu)體方法

orm的一個(gè)小案例

對(duì)反射的一些建議

三、網(wǎng)絡(luò)編程

socket編程

websocket編程

四、部署

打包命令

交叉編譯


一、單元測(cè)試

Go語(yǔ)言中自帶有一個(gè)輕量級(jí)的測(cè)試框架testing和自帶的go test命令來(lái)實(shí)現(xiàn)單元測(cè)試和性能測(cè)試,testing框架和其他語(yǔ)言的測(cè)試框架相似,可以基于這個(gè)框架寫針對(duì)相應(yīng)函數(shù)的測(cè)試用例,也可以基于該框架寫相應(yīng)的壓力測(cè)試用例。通過單元測(cè)試,可以解決:

  1. 確保每個(gè)函數(shù)是可運(yùn)行,并且運(yùn)行結(jié)果是正確的
  2. 確保寫出來(lái)的代碼性能是好的
  3. 單元測(cè)試能及時(shí)的發(fā)現(xiàn)程序設(shè)計(jì)或?qū)崿F(xiàn)的邏輯錯(cuò)誤,使問題暴露,便于問題的定位解決,而性能測(cè)試的重點(diǎn)在于發(fā)現(xiàn)程序設(shè)計(jì)上的一些問題,讓程序能夠在高并發(fā)的情況下還能保持穩(wěn)定

Go 語(yǔ)言推薦測(cè)試文件和源代碼文件放在一塊,測(cè)試文件以?_test.go?結(jié)尾

注意點(diǎn):

  1. 測(cè)試用例文件名必須以_test.go結(jié)尾
  2. 測(cè)試用例函數(shù)必須以Test開頭,一般來(lái)說就是Test+被測(cè)試的函數(shù)名?

單元測(cè)試?

例如我現(xiàn)在有兩個(gè)用于計(jì)算的文件,叫calc.go

package mainfunc Add(a int, b int) int {return a + b
}func Mul(a int, b int) int {return a * b
}

那么我的測(cè)試文件就是calc_test.go

package mainimport "testing"func TestAdd(t *testing.T) {if ans := Add(1, 2); ans != 3 {// 如果不符合預(yù)期,那就是測(cè)試不通過t.Errorf("1 + 2 expected be 3, but %d got", ans)}if ans := Add(-10, -20); ans != -30 {t.Errorf("-10 + -20 expected be -30, but %d got", ans)}
}

go test // 可以運(yùn)行某個(gè)包下的所有測(cè)試用例

-v?參數(shù)會(huì)顯示每個(gè)用例的測(cè)試結(jié)果

-run參數(shù)可以指定測(cè)試某個(gè)函數(shù)

單元測(cè)試框架提供的日志方法

方 法備 注測(cè)試結(jié)果
Log打印日志,同時(shí)結(jié)束測(cè)試PASS
Logf格式化打印日志,同時(shí)結(jié)束測(cè)試PASS
Error打印錯(cuò)誤日志,同時(shí)結(jié)束測(cè)試FAIL
Errorf格式化打印錯(cuò)誤日志,同時(shí)結(jié)束測(cè)試FAIL
Fatal打印致命日志,同時(shí)結(jié)束測(cè)試FAIL
Fatalf格式化打印致命日志,同時(shí)結(jié)束測(cè)試FAIL

?子測(cè)試

如果需要給一個(gè)函數(shù),調(diào)用不同的測(cè)試用例,可以使用子測(cè)試

子測(cè)試?yán)锩娴腇atal,是不會(huì)終止程序的

package mainimport "testing"func TestAdd(t1 *testing.T) {t1.Run("add1", func(t *testing.T) {if ans := Add(1, 2); ans != 3 {// 如果不符合預(yù)期,那就是測(cè)試不通過t.Fatalf("1 + 2 expected be 3, but %d got", ans)}})t1.Run("add2", func(t *testing.T) {if ans := Add(-10, -20); ans != -30 {t.Fatalf("-10 + -20 expected be -30, but %d got", ans)}})}

如果測(cè)試用例很多,還可以用一個(gè)類似表格去表示

package mainimport ("testing"
)func TestAdd(t *testing.T) {cases := []struct {Name           stringA, B, Expected int}{{"a1", 2, 3, 5},{"a2", 2, -3, -1},{"a3", 2, 0, 2},}for _, c := range cases {t.Run(c.Name, func(t *testing.T) {if ans := Add(c.A, c.B); ans != c.Expected {t.Fatalf("%d * %d expected %d, but %d got",c.A, c.B, c.Expected, ans)}})}
}

?TestMain

它是測(cè)試的入口

我們可以在TestMain里面實(shí)現(xiàn)測(cè)試流程的生命周期

package mainimport ("fmt""os""testing"
)// 測(cè)試前執(zhí)行
func setup() {fmt.Println("Before all tests")
}// 測(cè)試后執(zhí)行
func teardown() {fmt.Println("After all tests")
}func Test1(t *testing.T) {fmt.Println("I'm test1")
}func Test2(t *testing.T) {fmt.Println("I'm test2")
}// 必須叫這個(gè)名字  測(cè)試主入口
func TestMain(m *testing.M) {// 測(cè)試前執(zhí)行setup()code := m.Run()// 測(cè)試后執(zhí)行teardown()os.Exit(code)
}

二、反射

類型判斷

判斷一個(gè)變量是否是結(jié)構(gòu)體,切片,map

package mainimport ("fmt""reflect"
)func refType(obj any) {typeObj := reflect.TypeOf(obj)fmt.Println(typeObj, "+", typeObj.Kind())// 去判斷具體的類型switch typeObj.Kind() {case reflect.Slice:fmt.Println("切片")case reflect.Map:fmt.Println("map")case reflect.Struct:fmt.Println("結(jié)構(gòu)體")case reflect.String:fmt.Println("字符串")}
}func main() {refType(struct{ Name string }{Name: "os_lee"})name := "os_lee"refType(name)refType([]string{"os_lee"})
}

通過反射獲取值

package mainimport ("fmt""reflect"
)func refValue(obj any) {value := reflect.ValueOf(obj)fmt.Println(value, "+", value.Type())switch value.Kind() {case reflect.Int:fmt.Println("Int=", value.Int())case reflect.Struct:fmt.Println("Interface=", value.Interface())case reflect.String:fmt.Println("String=", value.String())}
}func main() {refValue(struct{ Name string }{Name: "os_lee"})name := "os_lee"refValue(name)refValue([]string{"os_lee"})
}

通過反射修改值

注意,如果需要通過反射修改值,必須要傳指針,在反射中使用Elem取指針對(duì)應(yīng)的值

結(jié)構(gòu)體反射

讀取json標(biāo)簽對(duì)應(yīng)的值,如果沒有就用屬性的名稱

這個(gè)示例很簡(jiǎn)單,沒有處理-和omitempty的情況

package mainimport ("fmt""reflect"
)type Student struct {Name stringAge  int `json:"age"`
}func main() {s := Student{Name: "os_lee",Age:  24,}t := reflect.TypeOf(s)v := reflect.ValueOf(s)for i := 0; i < t.NumField(); i++ {field := t.Field(i)jsonField := field.Tag.Get("json")if jsonField == "" {// 說明json的tag是空的jsonField = field.Name}fmt.Printf("Name: %s, type: %s, json: %s, value: %v\n", field.Name, field.Type, jsonField, v.Field(i))}
}

利用tag修改結(jié)構(gòu)體的某些值

例如,結(jié)構(gòu)體tag中有big的標(biāo)簽,就將值大寫

package mainimport ("fmt""reflect""strings"
)type Student struct {Name string `big:"name"`Addr string
}func main() {s := Student{Name: "os",Addr: "bj",}t := reflect.TypeOf(s)v := reflect.ValueOf(&s).Elem()for i := 0; i < t.NumField(); i++ {field := t.Field(i)bigField := field.Tag.Get("big")// 判斷類型是不是字符串if field.Type.Kind() != reflect.String {continue}if bigField == "" {continue}// 修改值valueFiled := v.Field(i)valueFiled.SetString(strings.ToTitle(valueFiled.String()))}fmt.Println(s)
}

調(diào)用結(jié)構(gòu)體方法

如果結(jié)構(gòu)體有call這個(gè)名字的方法,就執(zhí)行它

package mainimport ("fmt""reflect"
)type Student struct {Name stringAge  int
}func (Student) Look(name string) {fmt.Println("look name:", name)
}func (Student) See(name string) {fmt.Println("see name:", name)
}func main() {s := Student{Name: "os",Age:  21,}t := reflect.TypeOf(s)v := reflect.ValueOf(s)for i := 0; i < t.NumMethod(); i++ {methodType := t.Method(i)fmt.Println(methodType.Name, methodType.Type)if methodType.Name != "See" {continue}methodValue := v.Method(i)methodValue.Call([]reflect.Value{reflect.ValueOf("lee"), // 注意這里的類型})}
}

orm的一個(gè)小案例

package mainimport ("errors""fmt""reflect""strings"
)type Student struct {Name string `oslee-orm:"name"`Age  int    `oslee-orm:"age"`
}type UserInfo struct {Id   int    `oslee-orm:"id"`Name string `oslee-orm:"name"`Age  int    `oslee-orm:"age"`
}// sql, err := Find(Student{}, "name = ? and age = ?", "os_lee", 18)
func Find(obj any, query ...any) (sql string, err error) {// Find(Student, "name = ?", "os")// 希望能夠生成 select name, age from  where  name = 'os't := reflect.TypeOf(obj)//v := reflect.ValueOf(obj)// 首先得是結(jié)構(gòu)體對(duì)吧if t.Kind() != reflect.Struct {err = errors.New("非結(jié)構(gòu)體")return}// 拿全部字段// 拼接條件// 第二個(gè)參數(shù),中的問號(hào),就決定后面還能接多少參數(shù)var where stringif len(query) > 0 {// 有第二個(gè)參數(shù),校驗(yàn)第二個(gè)參數(shù)中的?個(gè)數(shù),是不是和后面的個(gè)數(shù)一樣q := query[0] // 理論上還要校驗(yàn)第二個(gè)參數(shù)的類型if strings.Count(q.(string), "?")+1 != len(query) {err = errors.New("參數(shù)個(gè)數(shù)不對(duì)")return}// 拼接where語(yǔ)句// 將?號(hào)帶入后面的參數(shù)for _, a := range query[1:] {// 替換q// 這里要判斷a的類型at := reflect.TypeOf(a)switch at.Kind() {case reflect.Int:q = strings.Replace(q.(string), "?", fmt.Sprintf("%d", a.(int)), 1)case reflect.String:q = strings.Replace(q.(string), "?", fmt.Sprintf("'%s'", a.(string)), 1)}}where += "where " + q.(string)}// 如果沒有第二個(gè)參數(shù),就是查全部// 拼接select// 拿所有字段,取oslee-orm對(duì)應(yīng)的值var columns []stringfor i := 0; i < t.NumField(); i++ {field := t.Field(i)f := field.Tag.Get("oslee-orm")// 不考慮是空的情況columns = append(columns, f)}// 結(jié)構(gòu)體的小寫名字+s做表名name := strings.ToLower(t.Name()) + "s"// 拼接最后的sqlsql = fmt.Sprintf("select %s from %s %s", strings.Join(columns, ","), name, where)return
}func main() {sql, err := Find(Student{}, "name = ? and age = ?", "os_lee", 18)fmt.Println(sql, err) // select name,age from students where name = 'os_lee' and age = 18sql, err = Find(UserInfo{}, "id = ?", 1)fmt.Println(sql, err) // select id,name,age from userinfos where id = 1
}

對(duì)反射的一些建議

如果是寫一下框架,偏底層工具類的操作

不用反射確實(shí)不太好寫,但是如果是在業(yè)務(wù)上,大量使用反射就不太合適了

因?yàn)榉瓷涞男阅軟]有正常代碼高,會(huì)慢個(gè)一到兩個(gè)數(shù)量級(jí)

使用反射可讀性也不太好,并且也不能在編譯期間發(fā)生錯(cuò)誤

三、網(wǎng)絡(luò)編程

socket編程

參考:5.網(wǎng)絡(luò)編程-socker(golang版)-CSDN博客

websocket編程

參考:4.網(wǎng)絡(luò)編程-websocket(golang)-CSDN博客

四、部署

go項(xiàng)目的部署特別簡(jiǎn)單,編寫完成之后,只需要執(zhí)行g(shù)o build即可打包為可執(zhí)行文件
注意,這個(gè)操作是不同平臺(tái)不一樣的
windows下打包就是exe文件,linux下打包就是二進(jìn)制文件

打包命令

go build

打當(dāng)前目錄下的main包,注意,只能有一個(gè)main函數(shù)的包

go build xxx.go

打當(dāng)前目錄下,xxx.go的包,這個(gè)包必須得是一個(gè)main包,不然沒有效果

go build -o main.exe xxx.go

強(qiáng)制對(duì)輸出的文件進(jìn)行重命名

-o參數(shù)必須得在文件的前面

交叉編譯

什么是交叉編譯呢,就是在windows上,我開發(fā)的go程序,我也能打包為linux上的可執(zhí)行程序

例如在windows平臺(tái),打linux的包

注意,執(zhí)行set這個(gè)命令,一定得要是在cmd的命令行下,powershell是無(wú)效的?

set CGO_ENABLED=0  
set GOOS=linux  
set GOARCH=amd64  
go build -o main main.go

?CGO_ENABLED : CGO 表示 golang 中的工具,CGO_ENABLED=0 表示 CGO 禁用,交叉編譯中不能使用 CGO GOOS : 環(huán)境變量用于指定目標(biāo)操作系統(tǒng),mac 對(duì)應(yīng) darwin,linux 對(duì)應(yīng) linux,windows 對(duì)應(yīng) windows ,還有其它的 freebsd、android 等

GOARCH:環(huán)境變量用于指定處理器的類型,386 也稱?x86?對(duì)應(yīng) 32位操作系統(tǒng)、amd64?也稱 x64 對(duì)應(yīng) 64 位操作系統(tǒng),arm?這種架構(gòu)一般用于嵌入式開發(fā)。比如?Android?,?iOS?,?Win mobile?等

為了方便呢,可以在項(xiàng)目的根目錄下寫一個(gè)bat文件

這樣就能快速構(gòu)建了

然后放到linux服務(wù)器下,設(shè)置文件權(quán)限就可以直接運(yùn)行了

chmod +x main
./main

再次注意啊,以后打包web項(xiàng)目的時(shí)候,配置文件和靜態(tài)文件等這些非go程序,是要一起復(fù)制到目標(biāo)服務(wù)器里面的

參考:Go 學(xué)習(xí)筆記(37)— 標(biāo)準(zhǔn)命令行工具(go build 跨平臺(tái)編譯、交叉編譯、go clean、go run、go fmt、go install、go get、go vet)-CSDN博客

http://www.risenshineclean.com/news/2929.html

相關(guān)文章:

  • 做網(wǎng)站的要多少錢怎樣推廣app
  • wordpress 標(biāo)簽 函數(shù)廣州優(yōu)化營(yíng)商環(huán)境條例
  • 外貿(mào)做雙語(yǔ)網(wǎng)站好還是單語(yǔ)網(wǎng)站seo搜索引擎優(yōu)化課后答案
  • 好網(wǎng)站建設(shè)公司的網(wǎng)站響應(yīng)式模版移動(dòng)優(yōu)化
  • bootstrap網(wǎng)站模版臺(tái)州關(guān)鍵詞優(yōu)化報(bào)價(jià)
  • 開封市住房和城鄉(xiāng)建設(shè)局網(wǎng)站做百度線上推廣
  • wordpress 復(fù)制網(wǎng)站競(jìng)價(jià)推廣網(wǎng)絡(luò)推廣運(yùn)營(yíng)
  • 汕頭網(wǎng)站制作電話網(wǎng)頁(yè)設(shè)計(jì)案例
  • 優(yōu)化大師好用嗎武漢網(wǎng)站seo推廣
  • 青島網(wǎng)站排名上海百網(wǎng)優(yōu)seo優(yōu)化公司
  • 網(wǎng)站后臺(tái)傳照片 c windows temp 拒絕訪問無(wú)錫百度信息流
  • 做現(xiàn)貨黃金網(wǎng)站體育熱點(diǎn)新聞
  • 網(wǎng)站圖片優(yōu)化怎么推廣自己的店鋪
  • wordpress最新版下載2022網(wǎng)站seo
  • 鄭州企業(yè)網(wǎng)站價(jià)格百度廣告搜索推廣
  • 做網(wǎng)站需要幾個(gè)服務(wù)器網(wǎng)絡(luò)營(yíng)銷自學(xué)網(wǎng)站
  • 優(yōu)化的網(wǎng)站做域名跳轉(zhuǎn)最新經(jīng)濟(jì)新聞
  • 英山縣住房和城鄉(xiāng)建設(shè)局網(wǎng)站搜索推廣開戶
  • wordpress分類目錄下文章過多_添加文章目錄導(dǎo)航關(guān)鍵詞優(yōu)化排名軟件s
  • 網(wǎng)站關(guān)鍵詞在哪里設(shè)置給公司做網(wǎng)站要多少錢
  • 用ih5做微網(wǎng)站平臺(tái)推廣費(fèi)用
  • 微網(wǎng)站制作價(jià)格頁(yè)面設(shè)計(jì)
  • 手機(jī)網(wǎng)站開發(fā)平臺(tái)互聯(lián)網(wǎng)營(yíng)銷怎么賺錢
  • 徐州中小企業(yè)網(wǎng)站制作中國(guó)局勢(shì)最新消息今天
  • 馬鞍山網(wǎng)站建設(shè) 明達(dá)百度收錄網(wǎng)站鏈接入口
  • 自己做的網(wǎng)站算廣告嗎公司網(wǎng)站域名續(xù)費(fèi)一年多少錢
  • 做美工哪個(gè)網(wǎng)站靠譜開封網(wǎng)站優(yōu)化公司
  • 網(wǎng)站網(wǎng)頁(yè)優(yōu)化怎么做上海推廣系統(tǒng)
  • 2018年做網(wǎng)站賺錢嗎百度一下首頁(yè)網(wǎng)頁(yè)百度
  • 南陽(yáng)市網(wǎng)站建設(shè)今天特大新聞最新消息