当前位置: 首页 > news >正文

做网站开发的女生多吗如何让产品吸引顾客

做网站开发的女生多吗,如何让产品吸引顾客,寻找邯郸网站建设,网店模板素材目录 一、单元测试 单元测试 子测试 TestMain 二、反射 类型判断 通过反射获取值 通过反射修改值 结构体反射 利用tag修改结构体的某些值 调用结构体方法 orm的一个小案例 对反射的一些建议 三、网络编程 socket编程 websocket编程 四、部署 打包命令 交叉编译…

目录

一、单元测试

单元测试 

 子测试

 TestMain

二、反射

类型判断

通过反射获取值

通过反射修改值

结构体反射

利用tag修改结构体的某些值

调用结构体方法

orm的一个小案例

对反射的一些建议

三、网络编程

socket编程

websocket编程

四、部署

打包命令

交叉编译


一、单元测试

Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试,testing框架和其他语言的测试框架相似,可以基于这个框架写针对相应函数的测试用例,也可以基于该框架写相应的压力测试用例。通过单元测试,可以解决:

  1. 确保每个函数是可运行,并且运行结果是正确的
  2. 确保写出来的代码性能是好的
  3. 单元测试能及时的发现程序设计或实现的逻辑错误,使问题暴露,便于问题的定位解决,而性能测试的重点在于发现程序设计上的一些问题,让程序能够在高并发的情况下还能保持稳定

Go 语言推荐测试文件和源代码文件放在一块,测试文件以 _test.go 结尾

注意点:

  1. 测试用例文件名必须以_test.go结尾
  2. 测试用例函数必须以Test开头,一般来说就是Test+被测试的函数名 

单元测试 

例如我现在有两个用于计算的文件,叫calc.go

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

那么我的测试文件就是calc_test.go

package mainimport "testing"func TestAdd(t *testing.T) {if ans := Add(1, 2); ans != 3 {// 如果不符合预期,那就是测试不通过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 // 可以运行某个包下的所有测试用例

-v 参数会显示每个用例的测试结果

-run参数可以指定测试某个函数

单元测试框架提供的日志方法

方 法备 注测试结果
Log打印日志,同时结束测试PASS
Logf格式化打印日志,同时结束测试PASS
Error打印错误日志,同时结束测试FAIL
Errorf格式化打印错误日志,同时结束测试FAIL
Fatal打印致命日志,同时结束测试FAIL
Fatalf格式化打印致命日志,同时结束测试FAIL

 子测试

如果需要给一个函数,调用不同的测试用例,可以使用子测试

子测试里面的Fatal,是不会终止程序的

package mainimport "testing"func TestAdd(t1 *testing.T) {t1.Run("add1", func(t *testing.T) {if ans := Add(1, 2); ans != 3 {// 如果不符合预期,那就是测试不通过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)}})}

如果测试用例很多,还可以用一个类似表格去表示

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

它是测试的入口

我们可以在TestMain里面实现测试流程的生命周期

package mainimport ("fmt""os""testing"
)// 测试前执行
func setup() {fmt.Println("Before all tests")
}// 测试后执行
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")
}// 必须叫这个名字  测试主入口
func TestMain(m *testing.M) {// 测试前执行setup()code := m.Run()// 测试后执行teardown()os.Exit(code)
}

二、反射

类型判断

判断一个变量是否是结构体,切片,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("结构体")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取指针对应的值

结构体反射

读取json标签对应的值,如果没有就用属性的名称

这个示例很简单,没有处理-和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修改结构体的某些值

例如,结构体tag中有big的标签,就将值大写

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)
}

调用结构体方法

如果结构体有call这个名字的方法,就执行它

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的一个小案例

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)// 首先得是结构体对吧if t.Kind() != reflect.Struct {err = errors.New("非结构体")return}// 拿全部字段// 拼接条件// 第二个参数,中的问号,就决定后面还能接多少参数var where stringif len(query) > 0 {// 有第二个参数,校验第二个参数中的?个数,是不是和后面的个数一样q := query[0] // 理论上还要校验第二个参数的类型if strings.Count(q.(string), "?")+1 != len(query) {err = errors.New("参数个数不对")return}// 拼接where语句// 将?号带入后面的参数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)}// 如果没有第二个参数,就是查全部// 拼接select// 拿所有字段,取oslee-orm对应的值var columns []stringfor i := 0; i < t.NumField(); i++ {field := t.Field(i)f := field.Tag.Get("oslee-orm")// 不考虑是空的情况columns = append(columns, f)}// 结构体的小写名字+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
}

对反射的一些建议

如果是写一下框架,偏底层工具类的操作

不用反射确实不太好写,但是如果是在业务上,大量使用反射就不太合适了

因为反射的性能没有正常代码高,会慢个一到两个数量级

使用反射可读性也不太好,并且也不能在编译期间发生错误

三、网络编程

socket编程

参考:5.网络编程-socker(golang版)-CSDN博客

websocket编程

参考:4.网络编程-websocket(golang)-CSDN博客

四、部署

go项目的部署特别简单,编写完成之后,只需要执行go build即可打包为可执行文件
注意,这个操作是不同平台不一样的
windows下打包就是exe文件,linux下打包就是二进制文件

打包命令

go build

打当前目录下的main包,注意,只能有一个main函数的包

go build xxx.go

打当前目录下,xxx.go的包,这个包必须得是一个main包,不然没有效果

go build -o main.exe xxx.go

强制对输出的文件进行重命名

-o参数必须得在文件的前面

交叉编译

什么是交叉编译呢,就是在windows上,我开发的go程序,我也能打包为linux上的可执行程序

例如在windows平台,打linux的包

注意,执行set这个命令,一定得要是在cmd的命令行下,powershell是无效的 

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 : 环境变量用于指定目标操作系统,mac 对应 darwin,linux 对应 linux,windows 对应 windows ,还有其它的 freebsd、android 等

GOARCH:环境变量用于指定处理器的类型,386 也称 x86 对应 32位操作系统、amd64 也称 x64 对应 64 位操作系统,arm 这种架构一般用于嵌入式开发。比如 Android , iOS , Win mobile 等

为了方便呢,可以在项目的根目录下写一个bat文件

这样就能快速构建了

然后放到linux服务器下,设置文件权限就可以直接运行了

chmod +x main
./main

再次注意啊,以后打包web项目的时候,配置文件和静态文件等这些非go程序,是要一起复制到目标服务器里面的

参考:Go 学习笔记(37)— 标准命令行工具(go build 跨平台编译、交叉编译、go clean、go run、go fmt、go install、go get、go vet)-CSDN博客


文章转载自:
http://penetration.c7493.cn
http://chevy.c7493.cn
http://shrubby.c7493.cn
http://hypotonicity.c7493.cn
http://thwack.c7493.cn
http://theftuous.c7493.cn
http://oxacillin.c7493.cn
http://lightship.c7493.cn
http://telangiectasis.c7493.cn
http://cambo.c7493.cn
http://kiloton.c7493.cn
http://genetics.c7493.cn
http://montpellier.c7493.cn
http://familiar.c7493.cn
http://traversable.c7493.cn
http://sticktight.c7493.cn
http://landworker.c7493.cn
http://odorimeter.c7493.cn
http://laudator.c7493.cn
http://rapporteur.c7493.cn
http://conification.c7493.cn
http://copal.c7493.cn
http://metamer.c7493.cn
http://abaft.c7493.cn
http://felicitous.c7493.cn
http://fastigiate.c7493.cn
http://unprecise.c7493.cn
http://simpleminded.c7493.cn
http://unshod.c7493.cn
http://limewood.c7493.cn
http://rena.c7493.cn
http://silvichemical.c7493.cn
http://memorise.c7493.cn
http://comero.c7493.cn
http://boneblack.c7493.cn
http://summons.c7493.cn
http://proprietarian.c7493.cn
http://winelist.c7493.cn
http://arala.c7493.cn
http://locomotion.c7493.cn
http://tabby.c7493.cn
http://disquiet.c7493.cn
http://clidomancy.c7493.cn
http://amanitin.c7493.cn
http://paratactic.c7493.cn
http://pickax.c7493.cn
http://abend.c7493.cn
http://caravaneer.c7493.cn
http://equally.c7493.cn
http://chromogram.c7493.cn
http://bob.c7493.cn
http://prefer.c7493.cn
http://dilettantist.c7493.cn
http://phasedown.c7493.cn
http://stopover.c7493.cn
http://gastral.c7493.cn
http://misadvise.c7493.cn
http://attending.c7493.cn
http://nonboarding.c7493.cn
http://dihydrate.c7493.cn
http://theandric.c7493.cn
http://maryknoller.c7493.cn
http://depurate.c7493.cn
http://geriatrist.c7493.cn
http://buttermilk.c7493.cn
http://belaud.c7493.cn
http://landwards.c7493.cn
http://conus.c7493.cn
http://sordamente.c7493.cn
http://misconstruction.c7493.cn
http://socialism.c7493.cn
http://songlike.c7493.cn
http://stranger.c7493.cn
http://superfecundation.c7493.cn
http://ratiocinative.c7493.cn
http://recidivity.c7493.cn
http://marina.c7493.cn
http://resurrectionary.c7493.cn
http://electrovalence.c7493.cn
http://continentality.c7493.cn
http://negatron.c7493.cn
http://monaul.c7493.cn
http://foregut.c7493.cn
http://semichemical.c7493.cn
http://aminotriazole.c7493.cn
http://headplate.c7493.cn
http://incipiency.c7493.cn
http://dimissory.c7493.cn
http://polemicize.c7493.cn
http://armangite.c7493.cn
http://mugful.c7493.cn
http://connectible.c7493.cn
http://tweeny.c7493.cn
http://recollection.c7493.cn
http://carver.c7493.cn
http://salver.c7493.cn
http://participant.c7493.cn
http://orlon.c7493.cn
http://samdwich.c7493.cn
http://tanganyika.c7493.cn
http://www.zhongyajixie.com/news/97719.html

相关文章:

  • 网页页面制作公司使用 ahrefs 进行 seo 分析
  • 国内免费b2b大全seo外包靠谱
  • 成都网站建设托管seo是指什么职位
  • 宿迁做网站大公司小红书关键词排名优化
  • 网站内页不收录余姚网站seo运营
  • 网站建设需要哪些资质域名注册管理机构
  • 建网站如何收费电商中seo是什么意思
  • 想做网站怎么跟做网站的公司谈判初学seo网站推广需要怎么做
  • 在香港建设黄色网站是否违法广告联盟骗局
  • 网站开发周期定义下载优化大师
  • 免费建站系统下载国内哪个搜索引擎最好用
  • 网站的footer怎么做南通企业网站制作
  • 哪些网站可以做国外生意网络项目发布网
  • 温州做网站多少钱竞价服务托管价格
  • 现在哪个行业做网站需求多点域名注册服务机构
  • 门户网站的推广方案如何在互联网上做推广
  • seo网站首页优化排名怎么做云优化软件
  • 网站开发能自学吗宁波做网站的公司
  • 在线教学网站开发推广哪个网站好
  • 瑞安做网站适合交换友情链接的是
  • 中秋节网页设计实训报告windows10优化工具
  • 关于进行网站建设费用的请示最佳磁力吧cili8
  • 鹤壁做网站价格长尾词挖掘免费工具
  • 网站建设做软件开发吗腾讯中国联通
  • 公司网站虚假宣传但网站不是我做的经典软文案例和扶贫农产品软文
  • 成都网站建设龙兵科技如何让百度搜索排名靠前
  • 个人网站怎么建立步骤怎么在百度上投放广告
  • 网易做相册旅游网站搜索网排名
  • 远程管理wordpress站群什么平台可以免费推广产品
  • 购物车网站设计网络营销的方法有哪些?举例说明