我想注册一个做门窗的网站应该怎样做网站美化的目标

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

我想注册一个做门窗的网站应该怎样做,网站美化的目标,广州网站公司,html个人网页制作教程目录 一、单元测试 单元测试 子测试 TestMain 二、反射 类型判断 通过反射获取值 通过反射修改值 结构体反射 利用tag修改结构体的某些值 调用结构体方法 orm的一个小案例 对反射的一些建议 三、网络编程 socket编程 websocket编程 四、部署 打包命令 交叉编译…目录 一、单元测试 单元测试  子测试 TestMain 二、反射 类型判断 通过反射获取值 通过反射修改值 结构体反射 利用tag修改结构体的某些值 调用结构体方法 orm的一个小案例 对反射的一些建议 三、网络编程 socket编程 websocket编程 四、部署 打包命令 交叉编译 一、单元测试 Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试testing框架和其他语言的测试框架相似可以基于这个框架写针对相应函数的测试用例也可以基于该框架写相应的压力测试用例。通过单元测试可以解决 确保每个函数是可运行并且运行结果是正确的确保写出来的代码性能是好的单元测试能及时的发现程序设计或实现的逻辑错误使问题暴露便于问题的定位解决而性能测试的重点在于发现程序设计上的一些问题让程序能够在高并发的情况下还能保持稳定 Go 语言推荐测试文件和源代码文件放在一块测试文件以 _test.go 结尾 注意点 测试用例文件名必须以_test.go结尾测试用例函数必须以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 testingfunc 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打印日志同时结束测试PASSLogf格式化打印日志同时结束测试PASSError打印错误日志同时结束测试FAILErrorf格式化打印错误日志同时结束测试FAILFatal打印致命日志同时结束测试FAILFatalf格式化打印致命日志同时结束测试FAIL 子测试 如果需要给一个函数调用不同的测试用例可以使用子测试 子测试里面的Fatal是不会终止程序的 package mainimport testingfunc 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 (fmtostesting )// 测试前执行 func setup() {fmt.Println(Before all tests) }// 测试后执行 func teardown() {fmt.Println(After all tests) }func Test1(t *testing.T) {fmt.Println(Im test1) }func Test2(t *testing.T) {fmt.Println(Im test2) }// 必须叫这个名字 测试主入口 func TestMain(m *testing.M) {// 测试前执行setup()code : m.Run()// 测试后执行teardown()os.Exit(code) }二、反射 类型判断 判断一个变量是否是结构体切片map package mainimport (fmtreflect )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_leerefType(name)refType([]string{os_lee}) } 通过反射获取值 package mainimport (fmtreflect )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_leerefValue(name)refValue([]string{os_lee}) }通过反射修改值 注意如果需要通过反射修改值必须要传指针在反射中使用Elem取指针对应的值 结构体反射 读取json标签对应的值如果没有就用属性的名称 这个示例很简单没有处理-和omitempty的情况 package mainimport (fmtreflect )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 (fmtreflectstrings )type Student struct {Name string big:nameAddr 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 (fmtreflect )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 (errorsfmtreflectstrings )type Student struct {Name string oslee-orm:nameAge int oslee-orm:age }type UserInfo struct {Id int oslee-orm:idName string oslee-orm:nameAge 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 ost : 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.网络编程-sockergolang版-CSDN博客 websocket编程 参考4.网络编程-websocketgolang-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_ENABLED0
set GOOSlinux
set GOARCHamd64
go build -o main main.go CGO_ENABLED : CGO 表示 golang 中的工具CGO_ENABLED0 表示 CGO 禁用交叉编译中不能使用 CGO GOOS : 环境变量用于指定目标操作系统mac 对应 darwinlinux 对应 linuxwindows 对应 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博客