如何修改Go包的源代码
How to modify the source code of a Go package
我正在尝试更改在 Go 的 src 文件夹中找到的 Sync 包的源代码。更具体地说,我需要更改 waitgroup.go 文件以导出 state() 函数。这是源函数:
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
} else {
return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
}
}
我需要做的就是将这个函数的名称大写,以便我可以在我的代码中使用它(我只需要检查 waitgoup 计数器是否大于 0)。我正在使用 Go Modules,到目前为止我找到的唯一解决方案是手动更改 waitgroup.go 文件夹中的 src 文件.这并不理想,因为更改未签入版本控制。我也尝试在我的代码库中重新创建 waitgroup.go 文件,但这会导致错误,因为该文件导入了 Go 的 internal[=40= 中的包]文件夹。
如何更改此 Go src 包的代码,同时通过版本控制 (github) 跟踪更改?
编辑
在某些情况下,我正在为加密货币设计点对点网络。下面的代码是我的同行发现系统的一部分。本质上,当第一次加入网络时,节点将通过 tcp 向 DNS 服务器发出请求,并随机 select 一个节点。然后它向节点(创世节点)发出请求,请求其本地节点集。一旦请求完成,即创世节点响应时,程序将进入第二个发现周期。我正在使用等待组等待第一个周期完成。
这是添加等待组的函数:
func HandleGenesisNode(request []byte) {
var buff bytes.Buffer
var payload RecieveGenesisNode
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
Handle(err)
//Initialize set with newly discovered node
InitSet(payload.GenesisNode)
//peer discovery first cycle
discoveryCycleOneWg.Add(1)
GetNodeSet(payload.GenesisNode)
//peer discovery second cycle once first has finished
discoveryCycleOneWg.Wait()
//Request the set of every node in the newly generated set
localSet := LocalSetToBytes()
for i := range localSet {
node := string(localSet[i])
GetNodeSet(node)
}
}
这是删除等待组以指示第一个周期已完成的函数:
func HandleLocalSet(request []byte) {
var buff bytes.Buffer
var payload LocalSet
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
Handle(err)
fmt.Println("Comparing sets...")
state, newNodes := CompareSet(payload.Set)
if state == true {
UpdateSet(newNodes)
} else {
fmt.Println("No new nodes discovered")
}
//allow second cycle to start if this is a response to discovery
//Check the waitgroup counter before decrementing it
_, wgState := discoveryCycleOneWg.State()
counter := uint32(wgState)
if counter > 0 {
discoveryCycleOneWg.Done()
}
}
尝试这样的事情:
package main
import (
"fmt"
"sync"
"sync/atomic"
_ "unsafe"
)
//go:linkname state sync.(*WaitGroup).state
func state(wg *sync.WaitGroup) (*uint64, *uint32)
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
statep, _ := state(&wg)
stateWg := atomic.LoadUint64(statep)
v := int32(stateWg >> 32)
fmt.Printf("%d", v)
}
关于 linkname
的文档
我正在尝试更改在 Go 的 src 文件夹中找到的 Sync 包的源代码。更具体地说,我需要更改 waitgroup.go 文件以导出 state() 函数。这是源函数:
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
} else {
return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
}
}
我需要做的就是将这个函数的名称大写,以便我可以在我的代码中使用它(我只需要检查 waitgoup 计数器是否大于 0)。我正在使用 Go Modules,到目前为止我找到的唯一解决方案是手动更改 waitgroup.go 文件夹中的 src 文件.这并不理想,因为更改未签入版本控制。我也尝试在我的代码库中重新创建 waitgroup.go 文件,但这会导致错误,因为该文件导入了 Go 的 internal[=40= 中的包]文件夹。
如何更改此 Go src 包的代码,同时通过版本控制 (github) 跟踪更改?
编辑
在某些情况下,我正在为加密货币设计点对点网络。下面的代码是我的同行发现系统的一部分。本质上,当第一次加入网络时,节点将通过 tcp 向 DNS 服务器发出请求,并随机 select 一个节点。然后它向节点(创世节点)发出请求,请求其本地节点集。一旦请求完成,即创世节点响应时,程序将进入第二个发现周期。我正在使用等待组等待第一个周期完成。
这是添加等待组的函数:
func HandleGenesisNode(request []byte) {
var buff bytes.Buffer
var payload RecieveGenesisNode
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
Handle(err)
//Initialize set with newly discovered node
InitSet(payload.GenesisNode)
//peer discovery first cycle
discoveryCycleOneWg.Add(1)
GetNodeSet(payload.GenesisNode)
//peer discovery second cycle once first has finished
discoveryCycleOneWg.Wait()
//Request the set of every node in the newly generated set
localSet := LocalSetToBytes()
for i := range localSet {
node := string(localSet[i])
GetNodeSet(node)
}
}
这是删除等待组以指示第一个周期已完成的函数:
func HandleLocalSet(request []byte) {
var buff bytes.Buffer
var payload LocalSet
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
Handle(err)
fmt.Println("Comparing sets...")
state, newNodes := CompareSet(payload.Set)
if state == true {
UpdateSet(newNodes)
} else {
fmt.Println("No new nodes discovered")
}
//allow second cycle to start if this is a response to discovery
//Check the waitgroup counter before decrementing it
_, wgState := discoveryCycleOneWg.State()
counter := uint32(wgState)
if counter > 0 {
discoveryCycleOneWg.Done()
}
}
尝试这样的事情:
package main
import (
"fmt"
"sync"
"sync/atomic"
_ "unsafe"
)
//go:linkname state sync.(*WaitGroup).state
func state(wg *sync.WaitGroup) (*uint64, *uint32)
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
statep, _ := state(&wg)
stateWg := atomic.LoadUint64(statep)
v := int32(stateWg >> 32)
fmt.Printf("%d", v)
}
关于 linkname
的文档