英文:
accessing objects from other files in go program
问题
Go语言的goji微框架有一个完全功能的示例应用程序,包含三个文件,分别是main.go
、models.go
和middleware.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 (
"fmt"
"io"
"net/http"
"regexp"
"strconv"
"github.com/zenazn/goji"
"github.com/zenazn/goji/param"
"github.com/zenazn/goji/web"
)
// 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("/", Root)
// Fully backwards compatible with net/http's Handlers
goji.Get("/greets", http.RedirectHandler("/", 301))
// Use your favorite HTTP verbs
goji.Post("/greets", NewGreet)
// Use Sinatra-style patterns in your URLs
goji.Get("/users/:name", GetUser)
// Goji also supports regular expressions with named capture groups.
goji.Get(regexp.MustCompile(`^/greets/(?P<id>\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("/admin/*", admin)
admin.Use(SuperSecure)
// Goji's routing, like Sinatra's, is exact: no effort is made to
// normalize trailing slashes.
goji.Get("/admin", http.RedirectHandler("/admin/", 301))
admin.Get("/admin/", AdminRoot)
admin.Get("/admin/finances", AdminFinances)
// Use a custom 404 handler
goji.NotFound(NotFound)
goji.Serve()
}
middleware.go
package main
import (
"encoding/base64"
"net/http"
"strings"
"github.com/zenazn/goji/web"
)
// 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("Content-Type", "text/plain")
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// Nobody will ever guess this!
const Password = "admin:admin"
// 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("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"
)
// 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:"user"`
Message string `param:"message"`
Time time.Time `param:"time"`
}
// Store all our greets in a big list in memory, because, let's be honest, who's
// actually going to use a service that only allows you to post 140-character
// messages?
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()},
}
// Write out a representation of the greet
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))
}
// 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't very many...
var Users = map[string]User{
"alice": {"Alice in Wonderland", "Eating mushrooms"},
"bob": {"Bob the Builder", "Making children dumber"},
"carl": {"Carl Jackson", "Duct tape aficionado"},
}
// Write out the user
func (u User) Write(w io.Writer, handle string) {
fmt.Fprintf(w, "%s (@%s)\n%s\n", u.Name, handle, u.Bio)
}
答案1
得分: 2
只需使用go run
或go 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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论