Go黑帽子(第一章)

2024-01-24 18:36
文章标签 go 第一章 帽子

本文主要是介绍Go黑帽子(第一章),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Go黑帽子渗透编程之道

文章目录

    • Go黑帽子渗透编程之道
      • 1.0 第一章 GO语言基础
        • 1.1 go build 命令
        • 1.2 交叉编译
        • 1.3 golint和go vet命令
        • 1.4 指针、接口和结构体
        • 1.5 断言
        • 1.6 错误处理
        • 1.7 处理结构化数据

1.0 第一章 GO语言基础

这一章我就不详细描述了我就记录一些我觉得比较有用和比较重要的东西,每一步我都会给出详细的解释,因为这不但可以加深我个人的理解而且可以给读者一个较好的阅读体验。

注意:不懂就找ChatGPT比什么博客解答的都详细

1.1 go build 命令
go build [文件名或包路径]
常用选项:
-o:指定输出文件的名称。
-v:输出详细的构建信息。
-a:强制重新构建所有的包,而不使用缓存的对象。
-x:打印每个命令及其参数。
-work:打印临时工作目录的路径。
-ldflags:传递链接器标志。
示例用法:
基本用法:go build main.go(编译当前目录下的 main.go 文件)。
指定输出文件名:go build -o myprogram main.go(将编译结果保存为 myprogram)。
输出详细信息:go build -v main.go(显示详细的构建信息)。
强制重新构建:go build -a main.go(强制重新构建所有包)。
打印每个命令:go build -x main.go(打印每个构建命令及其参数)。
打印临时工作目录:go build -work main.go(打印临时工作目录的路径)。
传递链接器标志:go build -ldflags="-s -w" main.go(传递链接器标志,这里是去除符号和禁用 DWARF 调试信息)。
其他注意事项:
如果在目录中执行 go build,它将尝试编译包含 main 函数的文件,生成可执行文件。如果是一个库(没有 main 函数的文件),它将构建库而不是可执行文件。
在构建过程中,Go 会自动下载并安装缺失的依赖项。
默认情况下,go build 不会生成输出文件,而是将结果保存在临时目录中。如果需要自定义输出文件名,可以使用 -o 选项。

传递链接器标志:go build -ldflags="-s -w" main.go(传递链接器标志,这里是去除符号和禁用 DWARF 调试信息)。

这条指令单独提出来的目的是,这条指令可以剥离一些不必要的信息从而减少二进制文件的大小,二进制文件越小,越能使你在一些极端情况下有效地进行传输和镶嵌。//我个人觉得这个后面或者以后的测试中肯定用的上,先埋个伏笔吧,等具体用上我再来补充这部分内容。

组合命令自己去尝试有助于加深理解。


1.2 交叉编译

创建可以在不同架构上可以运行的二进制文件

前提:设置一个约束限制,目的是为了将有关要为其编译代码的操作系统和架构信息传递给build命令的一种方法。

三种方式:命令行,代码注释或文件扩展名命名约定。

命令行:

windows下的指令
$env:GOOS="linux"; $env:GOARCH="amd64"; go build hello.go$env:GOOS="windows":这一部分使用 PowerShell 的 $env: 语法设置 GOOS 环境变量为 "windows",指示 Go 编译器生成 Windows 平台可执行文件。
$env:GOARCH="amd64":同样使用 PowerShell 的 $env: 语法设置 GOARCH 环境变量为 "amd64",指示 Go 编译器生成 64 位的可执行文件

这里留下了一个疑问:

当尝试交叉编译使用本机C环境绑定的应用程序时,会遇到真的“陷阱”,如果有大佬知道可以打在评论区供大家学习使用。


1.3 golint和go vet命令

golint:

golint 是 Go 语言中一个用于检查代码风格的工具,它会检查你的 Go 代码是否符合一些常见的编码规范。以下是 golint 的基本使用方法

安装:

go get golang.org/x/lint/golint
go install golang.org/x/lint/golint

运行 golint

在你的 Go 项目目录下,执行以下命令:

golint ./...

这个命令将会在当前目录下递归检查所有 Go 源代码文件,并输出不符合规范的代码行。

如果只想检查特定的文件或目录,可以指定相应的路径:

golint path/to/your/package

go vet:

go vet 命令用于检查 Go 代码中的常见错误和潜在问题。它能够检查代码中的诸多问题,包括但不限于未使用的变量、导入路径错误、printf 格式字符串错误等。以下是一些关于 go vet 命令的基本使用方法:

基本语法:

go vet [包名]

如果没有指定包名,则 go vet 将会检查当前目录及其子目录中的所有 Go 源文件。

示例:

go vet

或者,如果你想检查特定的包,可以使用:

go vet your/package/path

检查所有标准库:

go vet std

这个命令将检查所有标准库的 Go 源代码。

忽略特定的检查: 你可以使用 -vet 标志来指定要忽略的一些检查。例如,要忽略检查未导出的名字,你可以运行:

bashCopy code
go vet -vettool=$(which vet) -vetflags=-nointerfaceexport

这个命令使用 -vettool 指定 vet 工具,-vetflags 用于传递额外的参数。

在构建时运行: 你也可以在 go buildgo install 时一并运行 go vet

go build -vet all

go install -vet all

go vet 通常用于静态代码分析,帮助你发现可能的代码问题。注意,它并不是完美的,有些问题可能仍然需要通过其他手段检查。


1.4 指针、接口和结构体

指针:

var count = int(43)ptr := &countfmt.Println(ptr)fmt.Println(*ptr)//*ptr *书上说是取消该地址的引用,我的理解就是,修改所指向地址的值用**ptr = 100fmt.Println(count)//ptr存了count的地址,然后*ptr就是修改count地址的存储的值

接口和结构体

package mainimport "fmt"type Person struct {Name stringAge  int
}type Dog struct {
}func (p *Person) SayHello() {fmt.Println("hello", p.Name)
}
func (D *Dog) SayHello() {fmt.Println("woof")
}type Friend interface {SayHello()
}func Greet(f Friend) {f.SayHello()
}
func main() {var guy = new(Person)guy.Name = "laowang"guy.SayHello()//因为guy实现了Friend里面的所有方法,所以是Friend接口类Greet(guy)var dog = new(Dog)//传递给同一个函数Greet()多种类型Greet(dog)
}

1.5 断言
package mainimport "fmt"func Foo(i interface{}) {switch v := i.(type) {case int:fmt.Println(v, "is int")case string:fmt.Println(v, "is string")default:fmt.Println("UnKnow")}
}func main() {Foo(42)Foo("laowang")
}

1.6 错误处理

Go的内置错误错误类型没有隐式包含堆栈跟踪以帮助查明错误的上下文或位置。

package mainimport ("errors""fmt"
)type error interface {Error() string
}type MyError stringfunc (e MyError) Error() string {return string(e)
}func foo() error {return errors.New("Some Error Occurred")//你把上面的返回值修改之后你会发现,errors.New()方法的的error里面的Error()方法的返回值必须是error
}func main() {if err := foo(); err != nil {//处理错误fmt.Println(err)}
}

解释:

//个人理解:这里应该是重写了error错误处理接口,自定义了一个错误处理接口。
//在Go语言中,fmt.Println 函数在输出时会调用 String() 方法,如果类型实现了 String() string 方法,那么在打印该类型的值时就会调用这个方法。由于 error 接口包含了 Error() string 方法,而在 Go 语言中 error 接口经常用于表示错误,因此当你使用 fmt.Println 打印一个实现了 error 接口的值时,实际上会调用该值的 Error() 方法。
//代码中,err 是一个实现了 error 接口的值,它是 foo() 函数返回的错误。当你使用 fmt.Println(err) 时,fmt.Println 会调用 Error() 方法来获取错误的字符串表示形式,然后将其输出到标准输出。这就是为什么你可以直接通过 fmt.Println(err) 打印出错误信息的原因。

1.7 处理结构化数据

json

package mainimport ("encoding/json""fmt"
)type Foo struct {Bar stringBaz string
}func main() {f := Foo{"Hi", "Hello"}b, _ := json.Marshal(f)//这个b打印出来就是ASCII码fmt.Println(b)fmt.Println(string(b))//使用 json.Unmarshal//函数将 JSON 格式的字节切片 b 解码为 f 对象。//json.Unmarshal 接受两个参数,第一个是 JSON 数据的字节切片,第二个是目标对象的指针。//在这里,&f 表示将解码后的数据存储到 f 对象中。json.Unmarshal(b, &f)
}

这里序列化和反序列化就不详细介绍了,这里一般会和ORM框架一起使用,ORM 框架可以根据标签来自动生成数据库表或将数据库表映射到Go语言中的结构体。

总体来说,标签是一种元编程的手段,它允许程序员为代码添加元信息,以便在运行时或通过工具进行更灵活的操作。

这篇关于Go黑帽子(第一章)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/640604

相关文章

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

go基础知识归纳总结

无缓冲的 channel 和有缓冲的 channel 的区别? 在 Go 语言中,channel 是用来在 goroutines 之间传递数据的主要机制。它们有两种类型:无缓冲的 channel 和有缓冲的 channel。 无缓冲的 channel 行为:无缓冲的 channel 是一种同步的通信方式,发送和接收必须同时发生。如果一个 goroutine 试图通过无缓冲 channel

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(

Go Select的实现

select语法总结 select对应的每个case如果有已经准备好的case 则进行chan读写操作;若没有则执行defualt语句;若都没有则阻塞当前goroutine,直到某个chan准备好可读或可写,完成对应的case后退出。 Select的内存布局 了解chanel的实现后对select的语法有个疑问,select如何实现多路复用的,为什么没有在第一个channel操作时阻塞 从而导

Go Channel的实现

channel作为goroutine间通信和同步的重要途径,是Go runtime层实现CSP并发模型重要的成员。在不理解底层实现时,经常在使用中对channe相关语法的表现感到疑惑,尤其是select case的行为。因此在了解channel的应用前先看一眼channel的实现。 Channel内存布局 channel是go的内置类型,它可以被存储到变量中,可以作为函数的参数或返回值,它在r

Go 数组赋值问题

package mainimport "fmt"type Student struct {Name stringAge int}func main() {data := make(map[string]*Student)list := []Student{{Name:"a",Age:1},{Name:"b",Age:2},{Name:"c",Age:3},}// 错误 都指向了最后一个v// a

Go组合

摘要 golang并非完全面向对象的程序语言,为了实现面向对象的继承这一神奇的功能,golang允许struct间使用匿名引入的方式实现对象属性方法的组合 组合使用注意项 使用匿名引入的方式来组合其他struct 默认优先调用外层方法 可以指定匿名struct以调用内层方法 代码 package mainimport ("fmt")type People struct{}type Pe

Go语言构建单链表

package mainimport "fmt"type ListNode struct {Val intNext *ListNode}func main() {list := []int{2,4,3}head := &ListNode{Val:list[0]}tail := head //需要头尾两个指针for i:=1;i<len(list);i++ {//方法一 数组直接构建链表tai

Go 在orm中使用反射

作为静态语言,golang 稍显笨拙,还好 go 的标准包reflect(反射)包弥补了这点不足,它提供了一系列强大的 API,能够根据执行过程中对象的类型来改变程序控制流。本文将通过设计并实现一个简易的 mysql orm 来学习它,要求读者了解mysql基本知识,并且跟我一样至少已经接触 golang 两到三个月。 orm 这个概念相信同学们都非常熟悉,尤其是写过rails的同学,对acti