在函数内部导入

huangapple go评论83阅读模式
英文:

Import inside of a function

问题

正如标题所问,有没有办法在函数内部导入一个go文件?
我在考虑在我的discordgo(https://pkg.go.dev/github.com/bwmarrin/discordgo)程序中使用循环。

例如:

package main

import (
    ...
)

func main() {
    client, _ := disocrdgo.New("Bot " + mytoken)
    ...

    events, _ := ioutil.ReadDir("./events")
	for event, _ := range events {
		x, _ := import "MyApp/src/events/" + event // <---
        client.AddHandler(x.executor) // 使用类型结构,其中executor是我想从导入的文件中使用的函数
	}

    ...
}

我觉得有必要明确一下:
感谢您认真回答。

英文:

As the title asks, is there any way to import a go file from inside of a function?
I was thinking of using a loop for my discordgo(https://pkg.go.dev/github.com/bwmarrin/discordgo) program.

ex :

package main

import (
    ...
)

func main() {
    client, _ := disocrdgo.New(&quot;Bot &quot; + mytoken)
    ...


    events, _ := ioutil.ReadDir(&quot;./events&quot;)
	for event, _ := range events {
		x, _ := import &quot;MyApp/src/events/&quot; + event // &lt;---
        client.AddHandler(x.executor) // using type struct where executor is the function i want to use from the imported file
	}

    ...
}

I feel obligated to precise it so :
Thanks for your SERIOUS answers.

答案1

得分: 1

导入是编译器的概念,因此您无法在运行时导入包(通常情况下,运行程序的机器上甚至不存在源代码)。

您可以使用注册表模式来实现您所需的功能。

  • 在events包中,创建一个存储处理程序的函数。在每个事件处理程序包的init函数中调用该函数。
  • 在events包中,创建另一个函数,将存储的处理程序添加到客户端。
  • 在主包中,导入您需要的所有事件处理程序包,并调用该第二个函数。

这基本上是标准库中sql和image包的工作方式。请参见sql.Registerimage.RegisterFormat

// events/registry.go
package events

var handlers = map[string]interface{}{}

func Register(name string, h interface{}) {
    handlers[name] = h
}

func ConfigureClient(client *discordgo.Session) {
    for _, h := range handlers {
        client.AddHandler(h)
    }
}
// events/foo/foo.go
package foo

import "MyApp/src/events"

func init() {
    events.Register("foo", executor{})
}

type executor struct{}
// events/bar/bar.go
package bar

import "MyApp/src/events"

func init() {
    events.Register("bar", executor{})
}

type executor struct{}
// main.go
package main

import (
    _ "MyApp/src/events/foo"
    _ "MyApp/src/events/bar"
    // ...
)

func main() {
    client, _ := discordgo.New("Bot " + mytoken)
    events.ConfigureClient(client)
}
英文:

Imports are a compiler concept, so you cannot import packages at runtime (the source code doesn't even exist on the machine running your program, usually).

You can use the registry pattern to get close to what you're looking for.

  • In the events package, create a function that stores handlers. Call that function in the init function for each event handler package.
  • In the events package, create another function that adds the stored handlers to a client.
  • In the main package, import all event handler packages you need and call that second function.

This is more or less how the sql and image packages in the standard library work. See sql.Register and image.RegisterFormat.

// events/registry.go
package events

var handlers = map[string]interface{}{}

func Register(name string, h interface{}) {
	handlers[name] = h
}

func ConfigureClient(client *discordgo.Session) {
	for _, h := range handlers {
		client.AddHandler(h)
	}
}
// events/foo/foo.go
package foo

import &quot;MyApp/src/events&quot;

func init() {
    events.Register(&quot;foo&quot;, executor{})
}

type executor struct{}
// events/bar/bar.go
package bar

import &quot;MyApp/src/events&quot;

func init() {
    events.Register(&quot;bar&quot;, executor{})
}

type executor struct{}
// main.go
package main

import (
    _ &quot;MyApp/src/events/foo&quot;
    _ &quot;MyApp/src/events/bar&quot;
    // ...
)

func main() {
    client, _ := discordgo.New(&quot;Bot &quot; + mytoken)
    events.ConfigureClient(client)
}

huangapple
  • 本文由 发表于 2022年7月23日 08:32:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/73087236.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定