任务.任务未定义(类型为实体.任务没有字段或方法Task)


package entities
type Task struct {
Id       int64
task     string
assignee string
deadline string
action   string
}
package taskcontroller
import (
"fmt"
"html/template"
"net/http"
"github.com/jeypc/go-crud/config/entities"
)
func Index(response http.ResponseWriter, request *http.Request) {
temp, err := template.ParseFiles("config/views/task/index.html")
if err != nil {
panic(err)
}
temp.Execute(response, nil)
}
func Add(response http.ResponseWriter, request *http.Request) {
if request.Method == http.MethodGet {
temp, err := template.ParseFiles("config/views/task/add.html")
if err != nil {
panic(err)
}
temp.Execute(response, nil)
} else if request.Method == http.MethodPost {
request.ParseForm()
var task entities.Task
task.Task = request.Form.Get("task")
task.Assignee = request.Form.Get("assignee")
task.Deadline = request.Form.Get("deadline")
fmt.Println(task)
}
}

好的,所以这可能会被关闭,因为这是一个简单的打字错误,或者只是RT(f(M的一个例子。我建议你走一趟高尔夫之旅。导出的名称在基础的第3页中进行了解释,所以基本上是在教程开始时。如果你根本没有看过巡演,巡演从这里开始

尽管如此,我还是会用你的特定代码回答你的问题:

在戈兰,资本化很重要。在您的案例中,您有一个名为entities的包,在其中您定义了类型Task,其大写字母为T。因为您使用大写字母作为名称的第一个字符,所以类型为导出。当您在taskcontroller软件包中importentities软件包时,您将能够使用entities.Task。你写过吗:

package entities
type task struct {}

您将不能写入t := entities.task{}。用传统OOP术语来说:任何以小写字符开头的名称都是私有的。如果它们以大写字母开头,那么它们就是公共的。

现在看看你的类型:

type Task struct {
Id       int64
task     string
assignee string
deadline string
action   string
}

您有一个名为Task的公共类型,包含5个字段。一个字段(Id(是公共的,可以在entities包之外访问。其他四个字段是private,只能从entities包内部访问。

现在,您正在尝试在taskcontroller包中设置assigneetask等字段。你不能那样做,因为它们是私有。为了能够访问这些字段,最简单的方法是更改entities.Task类型并将字段公开:

type Task struct {
Id       int64
Task     string
Assignee string
Deadline string
Action   string
}

然后,您将能够访问其他包中的所有字段:

package taskcontroller
import "entities"
func someFunc() {
task := entities.Task{
Id:   123,
Task: "foo",
}
// or
task.Assignee = "bar"
}

不过,有时您可能希望限制/控制对类似字段的访问,在这种情况下,您可以使用getters/ssetter。同样,同样的规则适用于WRT资本化:

package entities
// Task as you have it now, with unexported fields
type Task struct {
Id       int64
task     string
assignee string
deadline string
action   string
}

// SetAssignee starts with upper-case S, so can be called from other packages
// this method can be used for validation/normalisation/...
// you'll need to add SetX for each field
func (t *Task) SetAssignee(assignee string) error {
if len(assignee) > 255 {
return errors.New("assignee too long, max length is 255")
}
// assignee is not exported, but using this function its value can be set
t.assignee = assignee
return nil
}
// GetAssignee is exported, can be called everywhere
// again, you'll need to implement a GetX for each unexported field
// can be used to return default values, for example
func (t Task) GetAssignee() string {
if len(t.assignee) == 0 {
return "none"
}
return t.assignee
}
func (t *Task) ToMapAndClear() map[string]interface{} {
// create a map containing the data
r := map[string]interface{}{
"id":       t.Id,
"task":     t.task,
"assignee": t.assignee,
"deadline": t.deadline,
"action":   t.action,
}
// clear all fields. We can call reset from inside the package
t.reset()
return r
}
// ExtractMap same function as above, but with defer so it's less verbose
func (t *Task) ExtractMap() map[string]interface{} {
defer t.reset()
return map[string]interface{
"id":       t.Id,
"task":     t.task,
"assignee": t.assignee,
"deadline": t.deadline,
"action":   t.action,
}
}
// reset starts with lower-case s, so cannot be called outside of this package
func (t *Task) reset() {
*t = Task{}
}

通过这些方法,您可以在其他包中使用entities.Task类型,如

package main
import (
"fmt"
"entities"
)
func main() {
t := entities.Task{
Id: 123,
}
if err := t.SetAssignee("Benjamin"); err != nil {
fmt.Printf("Could not set assignee: %vn", err)
return
}
fmt.Printf("Task assigned to %sn", t.GetAssignee()) // works fine
// does not work
t.reset() // main package does not have access to reset method
// this does work - we get the values in a map, and reset gets called internally
data := t.ExtractMap()
}

正如您所看到的,虽然我不能在main包之外直接调用reset,但我可以调用内部调用reset的导出方法。

最新更新