英文:
Restrict variable to itself and to other certain package
问题
我有这样的结构:
├── app
│ ├── app.go
│ ├── handler
│ │ ├── common.go
│ │ └── users.go
│ ├── model
│ │ └── model.go
│ └── queries
│ └── queries.go
├── config
│ └── config.go
└── main.go
所有的查询(SQL查询)都在 queries.go
中:
queries.go:
package queries
const (
QueryFindUser = `SELECT * FROM users WHERE id=$1` // <------ 这里
)
users.go:
package handler
import (
"GO_APP/app/model"
"GO_APP/app/queries"
"fmt"
"net/http"
"strconv"
"github.com/julienschmidt/httprouter"
_ "github.com/jinzhu/gorm/dialects/postgres"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
// getUserOr404 gets a User instance if exists, or respond the 404 error otherwise
func getUserOr404(db *sqlx.DB, id int, w http.ResponseWriter, r *http.Request) (*model.User, error) {
user := model.User{}
err := db.Get(&user, queries.QueryFindUser, id) // <----- 这里
return &user, err
}
如果我使用 QueryFindUser
(首字母大写),那么它将对所有其他包可见。但我不希望它可以被 config/config.go
等访问。
我希望它仅限于 handler
的模块,不包括 model/model.go
。
如果我声明 queryFindUser
,那么它将仅限于 queries
包,我将无法在其他地方使用它。
如何解决这个问题?而不使它对每个其他包都可见。
我对golang/java还很陌生,这个问题在java中也是一样的。
那么在这种情况下该怎么办?
如果您能提供一些资源,对我来说也会很有帮助。
英文:
I have this structure:
├── app
│ ├── app.go
│ ├── handler
│ │ ├── common.go
│ │ └── users.go
│ ├── model
│ │ └── model.go
│ └── queries
│ └── queries.go
├── config
│ └── config.go
└── main.go
All my queries (SQL ones) are in queries.go
:
queries.go:
package queries
const (
QueryFindUser = `SELECT * FROM users WHERE id=$1` // <------ HERE
)
users.go:
package handler
import (
"GO_APP/app/model"
"GO_APP/app/queries"
"fmt"
"net/http"
"strconv"
"github.com/julienschmidt/httprouter"
_ "github.com/jinzhu/gorm/dialects/postgres"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
// getUserOr404 gets a User instance if exists, or respond the 404 error otherwise
func getUserOr404(db *sqlx.DB, id int, w http.ResponseWriter, r *http.Request) (*model.User, error) {
user := model.User{}
err := db.Get(&user, queries.QueryFindUser, id) // <----- Here
return &user, err
}
If I use QueryFindUser
(capital first letter) then it will become exportable to all the other packages. But I don't want this to be accessible by say config/config.go
I want it to be restricted to handler
's modules only exlcluding the model/model.go
.
If I declare queryFindUser
this will be limited to the package queries
only and then I won't be able to use it anywhere.
How to solve this thing? Without making it exportable to every other package.
I am quite new to golang/java and this issue will be same in java as well.
So what to do in this case?
If you can provide resources that will also be helpful to me.
答案1
得分: 1
访问标识符的权限并不是非常精细,你无法指定授予访问权限的对象。而且也没有必要这样做。这样做只会不必要地增加使用(源代码)和实现(编译时间、编译包对象和可执行二进制文件大小)的复杂性。
如果你只想给一个特定的包访问权限,最简单的方法是合并这些包并将标识符设为非导出。
如果你想给多个包或者包会变得非常庞大,你可以使用内部包。内部包的引入使得你可以将“大”包拆分为多个较小的包,同时仍然可以隐藏和保护实现细节,使其对“外部”(其他包)不可见。
内部包可以定义导出的标识符,但只允许“内部组”访问它们。
例如:
├── app
│ ├── app.go
│ ├── handler
│ │ ├── internal
│ │ │ ├── queries
│ │ │ │ └── queries.go
│ │ │ └── foo
│ │ │ └── foo.go
│ │ ├── users.go
│ │ ├── common.go
│ │ └── users.go
│ └── model
│ └── model.go
├── config
│ └── config.go
└── main.go
在这个例子中,queries
包可以被handler
包和foo
包访问,但不能被model
包或config
包访问。
一般来说,内部包(位于路径中具有internal
文件夹的文件夹内的包)只能从父级internal
文件夹的根目录下的包中导入。
参考相关问题:
https://stackoverflow.com/questions/59342373/use-of-internal-package-not-allowed/59342483#59342483
英文:
Access permission to identifiers is not so fine grained that you can specify who you're granting access. And there's no need. This would unnecessarily complicate both the uses (source code) and the implementation (compilation time, compiled package object and executable binary size).
If you want to give access to a specific package only, easiest is to merge the packages and make the identifiers unexported.
If you want to give access to multiple packages or the package would get unpleasantly big, you may use internal packages. Internal packages were introduced so you can break "big" packages into multiple, smaller ones, and still keep the implementation detail hidden and protected from the "outside" (from other packages).
Internal packages may define exported identifiers, but access to them is only allowed to the "internal group".
For example:
├── app
│ ├── app.go
│ ├── handler
│ │ ├── internal
│ │ │ ├── queries
│ │ │ │ └── queries.go
│ │ │ └── foo
│ │ │ └── foo.go
│ │ ├── users.go
│ │ ├── common.go
│ │ └── users.go
│ └── model
│ └── model.go
├── config
│ └── config.go
└── main.go
In this example the queries
package is accessible by the handler
package and by the foo
package, but is not accessible by the model
or config
packages.
In general, internal packages (packages that are inside a folder that has an internal
folder in their path) can only be imported from packages rooted at the parent of the internal
folder.
See related questions:
https://stackoverflow.com/questions/59342373/use-of-internal-package-not-allowed/59342483#59342483
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论