在Go程序中访问其他文件中的对象。

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

accessing objects from other files in go program

问题

Go语言的goji微框架有一个完全功能的示例应用程序,包含三个文件,分别是main.gomodels.gomiddleware.go。我使用go get命令安装了这个框架:

go get github.com/zenazn/goji

因此,在我的GOPATH中可以找到示例应用程序,路径如下:

src/github.com/zenazn/goji/example

如果我进入/example/目录并运行go run main.go,会出现错误,指示main.go文件无法访问middleware.go和models.go文件中的对象,错误信息如下:

./main.go:39: undefined: PlainText
./main.go:47: undefined: SuperSecure
./main.go:73: undefined: Greets
./main.go:74: undefined: Greets
./main.go:85: undefined: Greet
./main.go:98: undefined: Greets
./main.go:99: undefined: Greets
./main.go:107: undefined: Users
./main.go:116: undefined: Greets
./main.go:116: too many errors

在main.go中没有导入middleware.go或models.go的代码,只有导入库的常规导入语句。

这些文件应该如何关联起来,以便一个文件中的对象可以在另一个文件中使用呢?

main.go中的代码如下:

package main

import (
    "fmt"
    "io"
    "net/http"
    "regexp"
    "strconv"

    "github.com/zenazn/goji"
    "github.com/zenazn/goji/param"
    "github.com/zenazn/goji/web"
)

// 注意:为了简化示例应用程序,下面的代码做了很多简化。

func main() {
    // 将路由添加到全局处理程序
    goji.Get("/", Root)
    // 完全兼容net/http的处理程序
    goji.Get("/greets", http.RedirectHandler("/", 301))
    // 使用您喜欢的HTTP动词
    goji.Post("/greets", NewGreet)
    // 在URL中使用Sinatra样式的模式
    goji.Get("/users/:name", GetUser)
    // Goji还支持带有命名捕获组的正则表达式。
    goji.Get(regexp.MustCompile(`^/greets/(?P<id>\d+)$`), GetGreet)

    // 中间件可用于向应用程序注入行为。该应用程序的中间件在middleware.go中定义,但您可以将它们放在任何地方。
    goji.Use(PlainText)

    admin := web.New()
    goji.Handle("/admin/*", admin)
    admin.Use(SuperSecure)

    // Goji的路由与Sinatra的路由一样精确:不会尝试规范化尾部斜杠。
    goji.Get("/admin", http.RedirectHandler("/admin/", 301))

    admin.Get("/admin/", AdminRoot)
    admin.Get("/admin/finances", AdminFinances)

    // 使用自定义的404处理程序
    goji.NotFound(NotFound)

    goji.Serve()
}

middleware.go

package main

import (
    "encoding/base64"
    "net/http"
    "strings"

    "github.com/zenazn/goji/web"
)

// PlainText将响应的内容类型设置为text/plain。
func PlainText(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/plain")
        h.ServeHTTP(w, r)
    }
    return http.HandlerFunc(fn)
}

// 没有人会猜到这个密码!
const Password = "admin:admin"

// SuperSecure是用于超级秘密管理员页面的HTTP基本身份验证中间件。嘘!
func SuperSecure(c *web.C, h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        auth := r.Header.Get("Authorization")
        if !strings.HasPrefix(auth, "Basic ") {
            pleaseAuth(w)
            return
        }

        password, err := base64.StdEncoding.DecodeString(auth[6:])
        if err != nil || string(password) != Password {
            pleaseAuth(w)
            return
        }

        h.ServeHTTP(w, r)
    }
    return http.HandlerFunc(fn)
}

func pleaseAuth(w http.ResponseWriter) {
    w.Header().Set("WWW-Authenticate", `Basic realm="Gritter"`)
    w.WriteHeader(http.StatusUnauthorized)
    w.Write([]byte("Go away!\n"))
}

models.go

package main

import (
    "fmt"
    "io"
    "time"
)

// Greet是一个140个字符的微博帖子,与鸟叫声毫无相似之处。
type Greet struct {
    User    string    `param:"user"`
    Message string    `param:"message"`
    Time    time.Time `param:"time"`
}

// 将所有的问候语存储在一个大的内存列表中,因为,说实话,谁会使用一个只允许发布140个字符消息的服务呢?
var Greets = []Greet{
    {"carl", "Welcome to Gritter!", time.Now()},
    {"alice", "Wanna know a secret?", time.Now()},
    {"bob", "Okay!", time.Now()},
    {"eve", "I'm listening...", time.Now()},
}

// 写出问候语的表示
func (g Greet) Write(w io.Writer) {
    fmt.Fprintf(w, "%s\n@%s at %s\n---\n", g.Message, g.User,
        g.Time.Format(time.UnixDate))
}

// User是一个人。它甚至可能是你认识的人。或者是一只兔子。很难从这里说。
type User struct {
    Name, Bio string
}

// 我们知道的所有用户!并不是很多...
var Users = map[string]User{
    "alice": {"Alice in Wonderland", "Eating mushrooms"},
    "bob":   {"Bob the Builder", "Making children dumber"},
    "carl":  {"Carl Jackson", "Duct tape aficionado"},
}

// 写出用户
func (u User) Write(w io.Writer, handle string) {
    fmt.Fprintf(w, "%s (@%s)\n%s\n", u.Name, handle, u.Bio)
}
英文:

The goji microframework for Go has a fully functional example app with three files, main.go, models.go and middleware.go. I installed the framework using the go get command

go get github.com/zenazn/goji

and therefore have the example app availabl in my GOPATH like this

src/github.com/zenazn/goji/example

if I navigate to /example/ and run go run main.go, it gives me errors which indicate that the main.go file is isn't accessing the objects from the middleware.go and models.go files, like this

./main.go:39: undefined: PlainText
./main.go:47: undefined: SuperSecure
./main.go:73: undefined: Greets
./main.go:74: undefined: Greets
./main.go:85: undefined: Greet
./main.go:98: undefined: Greets
./main.go:99: undefined: Greets
./main.go:107: undefined: Users
./main.go:116: undefined: Greets
./main.go:116: too many errors

There is no code in main.go that imports middleware.go or models.go, only the regular import statements for libraries.

How are these files supposed to be tied together so that the objects from one are available in the other?

from main.go

package main

import (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;net/http&quot;
	&quot;regexp&quot;
	&quot;strconv&quot;

	&quot;github.com/zenazn/goji&quot;
	&quot;github.com/zenazn/goji/param&quot;
	&quot;github.com/zenazn/goji/web&quot;
)

// Note: the code below cuts a lot of corners to make the example app simple.

func main() {
	// Add routes to the global handler
	goji.Get(&quot;/&quot;, Root)
	// Fully backwards compatible with net/http&#39;s Handlers
	goji.Get(&quot;/greets&quot;, http.RedirectHandler(&quot;/&quot;, 301))
	// Use your favorite HTTP verbs
	goji.Post(&quot;/greets&quot;, NewGreet)
	// Use Sinatra-style patterns in your URLs
	goji.Get(&quot;/users/:name&quot;, GetUser)
	// Goji also supports regular expressions with named capture groups.
	goji.Get(regexp.MustCompile(`^/greets/(?P&lt;id&gt;\d+)$`), GetGreet)

	// Middleware can be used to inject behavior into your app. The
	// middleware for this application are defined in middleware.go, but you
	// can put them wherever you like.
	goji.Use(PlainText)

	admin := web.New()
	goji.Handle(&quot;/admin/*&quot;, admin)
	admin.Use(SuperSecure)

	// Goji&#39;s routing, like Sinatra&#39;s, is exact: no effort is made to
	// normalize trailing slashes.
	goji.Get(&quot;/admin&quot;, http.RedirectHandler(&quot;/admin/&quot;, 301))


	admin.Get(&quot;/admin/&quot;, AdminRoot)
	admin.Get(&quot;/admin/finances&quot;, AdminFinances)

	// Use a custom 404 handler
	goji.NotFound(NotFound)

	goji.Serve()
}

middleware.go

package main

import (
	&quot;encoding/base64&quot;
	&quot;net/http&quot;
	&quot;strings&quot;

	&quot;github.com/zenazn/goji/web&quot;
)

// PlainText sets the content-type of responses to text/plain.
func PlainText(h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set(&quot;Content-Type&quot;, &quot;text/plain&quot;)
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(fn)
}

// Nobody will ever guess this!
const Password = &quot;admin:admin&quot;

// SuperSecure is HTTP Basic Auth middleware for super-secret admin page. Shhhh!
func SuperSecure(c *web.C, h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		auth := r.Header.Get(&quot;Authorization&quot;)
		if !strings.HasPrefix(auth, &quot;Basic &quot;) {
			pleaseAuth(w)
			return
		}

		password, err := base64.StdEncoding.DecodeString(auth[6:])
		if err != nil || string(password) != Password {
			pleaseAuth(w)
			return
		}

		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(fn)
}

func pleaseAuth(w http.ResponseWriter) {
	w.Header().Set(&quot;WWW-Authenticate&quot;, `Basic realm=&quot;Gritter&quot;`)
	w.WriteHeader(http.StatusUnauthorized)
	w.Write([]byte(&quot;Go away!\n&quot;))
}

models.go

package main

import (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;time&quot;
)

// A Greet is a 140-character micro-blogpost that has no resemblance whatsoever
// to the noise a bird makes.
type Greet struct {
	User    string    `param:&quot;user&quot;`
	Message string    `param:&quot;message&quot;`
	Time    time.Time `param:&quot;time&quot;`
}

// Store all our greets in a big list in memory, because, let&#39;s be honest, who&#39;s
// actually going to use a service that only allows you to post 140-character
// messages?
var Greets = []Greet{
	{&quot;carl&quot;, &quot;Welcome to Gritter!&quot;, time.Now()},
	{&quot;alice&quot;, &quot;Wanna know a secret?&quot;, time.Now()},
	{&quot;bob&quot;, &quot;Okay!&quot;, time.Now()},
	{&quot;eve&quot;, &quot;I&#39;m listening...&quot;, time.Now()},
}

// Write out a representation of the greet
func (g Greet) Write(w io.Writer) {
	fmt.Fprintf(w, &quot;%s\n@%s at %s\n---\n&quot;, g.Message, g.User,
		g.Time.Format(time.UnixDate))
}

// A User is a person. It may even be someone you know. Or a rabbit. Hard to say
// from here.
type User struct {
	Name, Bio string
}

// All the users we know about! There aren&#39;t very many...
var Users = map[string]User{
	&quot;alice&quot;: {&quot;Alice in Wonderland&quot;, &quot;Eating mushrooms&quot;},
	&quot;bob&quot;:   {&quot;Bob the Builder&quot;, &quot;Making children dumber&quot;},
	&quot;carl&quot;:  {&quot;Carl Jackson&quot;, &quot;Duct tape aficionado&quot;},
}

// Write out the user
func (u User) Write(w io.Writer, handle string) {
	fmt.Fprintf(w, &quot;%s (@%s)\n%s\n&quot;, u.Name, handle, u.Bio)
}

答案1

得分: 2

只需使用go rungo run *.go,你只会运行/编译main.go文件,其他文件不会被包含进去。

英文:

Just use go run or go run *.go you are running/compiling only main.go the other files are not included.

答案2

得分: 0

你最好使用go build命令来构建一个二进制文件,然后可以通过./example来运行它。

Go语言操作的是包(packages),而不是文件,go run命令只是一个方便的工具,用于测试示例或简单的程序(它会构建二进制文件并且丢弃它)。

英文:

You should, preferably, be using go build - to build a binary which you can then run as ./example.

Go operates on packages, not files, and go run is ultimately just a convenience to be used when testing examples or simple programs (it builds the binary and discards it, effectively).

huangapple
  • 本文由 发表于 2014年7月9日 03:37:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/24640352.html
匿名

发表评论

匿名网友

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

确定