在Golang中出现了包导入错误。

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

Package Import error on Golang

问题

我的回答如下:

我的帖子有两个问题。

我主要想了解如何在gingko中使用gomock。

GOPATH路径为/Users/Ratatouille/Desktop/test/goExample

以下项目位于/Users/Ratatouille/Desktop/test/goExample/square,具有以下项目结构:

.
├── area.go
└── area_test
    ├── area_mock.go
    ├── area_mock_test.go
    └── area_suite_test.go

我不明白为什么会出现以下错误:

Failed to compile area_test:

can't load package: package ./area_test: found packages area_test (area_mock.go) and area (area_mock_test.go) in /Users/Ratatouille/Desktop/test/goExample/square/area_test

Ginkgo ran 1 suite in 303.243871ms
Test Suite Failed

我的第二个问题是项目仓库中有一个名为area.go的文件,内容如下:

package main

import "fmt"

type Square struct {
	side float32
}

func (s *Square) Area() float32 {
	return s.side * s.side
}

func (s *Square) CalculateArea(shaper Shaper) float32 {
	shaper.Area()
}

type Shaper interface {
	Area() float32
}

func main() {
	sq1 := new(Square)
	sq1.side = 2

	var areaIntf Shaper
	areaIntf = sq1
	fmt.Println(areaIntf.Area())
}

我的问题是如何在area_mock_test.go导入main包。

英文:

My post has 2 question

I'm essentially trying to understand how to use gomock with gingko

GOPATH

/Users/Ratatouille/Desktop/test/goExample

The following project is located at

/Users/Ratatouille/Desktop/test/goExample/square

which has following project structure

.
├── area.go
└── area_test
    ├── area_mock.go
    ├── area_mock_test.go
    └── area_suite_test.go

what I'm not able to understand why I'm getting following error

Failed to compile area_test:

can't load package: package ./area_test: found packages area_test (area_mock.go) and area (area_mock_test.go) in /Users/Ratatouille/Desktop/test/goExample/square/area_test

Ginkgo ran 1 suite in 303.243871ms
Test Suite Failed

my second question is project repo has area.go file which look like this

package main

import "fmt"

type Square struct {
	side float32
}

func (s *Square) Area() float32 {
	return s.side * s.side
}

func (s *Square) CalculateArea(shaper Shaper) float32 {
	shaper.Area()
}

type Shaper interface {
	Area() float32
}

func main() {
	sq1 := new(Square)
	sq1.side = 2

	var areaIntf Shaper
	areaIntf = sq1
	fmt.Println(areaIntf.Area())
}

My question is how do I import main package inside area_mock_test.go

答案1

得分: 2

你的项目结构不符合Go的要求。

area_test/不是area的测试。我猜你运行了go test ./area_test。这告诉Go ./area_test是一个项目。它试图编译area_mock.go,并尝试使用area_mock_test.goarea_suite_test.go作为它的测试。你得到的错误是Go告诉你它不希望在项目文件中找到名为*_test的包的奇怪方式。


area.go也有问题。你将其使用package main,但是尝试使用package area_test进行测试。它们不匹配,Go不会喜欢。一个包目录包含一个包。它的测试必须使用该包或thatpackage_test。这强制要求一个包目录只做一件事。它要么是一个要导入的库,要么是一个要运行的程序。不能两者兼而有之。

此外,项目目录被称为square,但包名是area。文件名与项目名不匹配是可以的,一个包中可以有多个文件,但是使用与项目目录名不同的包名不是好的做法。


还有一个问题。Go希望源文件在$GOPATH/src中。你直接将它们放在$GOPATH中是不行的。导入语句找不到它们。


Go的项目结构可能需要一些时间来适应,它对项目和包的结构有非常明确的想法(Go对代码的编写方式和不编写方式有非常明确的想法)。不要与之对抗。为自己做个好事,使用默认的GOPATH,即~/go,并将代码放在~/go/src/中。

你可以这样编写square库。

~/go/src/square/
|--- square.go
|--- square_test.go

square.go可能如下所示。

package square

type Square struct {
    Side float32
}

func (s Square) Area() float32 {
    return s.Side * s.Side
}

注意,为了使Side成为公共数据成员,它必须大写。还要注意,它是按值传递的,在Go中,如果你打算修改结构体,只传递指针。

square_test.go可能如下所示。

package square_test

import(
    "testing"
    "square"
    "github.com/stvp/assert"
)

func TestArea(t *testing.T) {
    sq := square.Square{Side: 5}
    
    assert.Equal(t, sq.Area(), float32(25))
}

Go不带有任何断言。github.com/stvp/assert提供了基本的断言并消除了很多冗余。你可以使用go get github.com/stvp/assert获取它。

请注意,它位于package square_test中,以使其成为一个只能使用square的公共接口的黑盒测试。如果你想要一个白盒/内部测试,它将使用package square,并在自己的文件中,如square_internal_test.go

如果你想要一个使用square的程序,那将是一个独立的包目录。它将有一个main.go,其中包含package mainimport "square"

如何编写Go代码对此进行了更详细的解释。

英文:

Your project structure isn't the one Go expects.

area_test/ are not the tests for area. I'm going to guess you ran go test ./area_test. That tells Go that ./area_test is a project. It tried to compile area_mock.go and tried to use area_mock_test.go and area_suite_test.go as its tests. The error you got is Go's awkward way of telling you that it did not expect to find a package named *_test in a project file.


area.go is also a problem. You have it using package main, but then try to test with package area_test. They don't match and Go won't like it. A package directory contains one package. Its tests must use either that package or thatpackage_test. This enforces that a package directory does one thing. Its either a library to import, or its a program to run. Not both.

Also the project directory is called square, but the package is area. It's ok to have files that don't match the project name, and its fine to have multiple files in one package, but using a package than the project directory name is not good practice.


There's another problem. Go expects source files to be in $GOPATH/src. You have them directly in $GOPATH. Import statements won't find them.


Go's project structure can take a bit of getting used to, and it has very firm ideas about how projects and packages are to be structured (Go has very firm ideas about how code is to be written, and how it isn't). Don't fight it. Do yourself a favor and use the default GOPATH of ~/go and put your code in ~/go/src/.

You'd write the square library like so.

~/go/src/square/
|--- square.go
|--- square_test.go

square.go might look like this.

package square

type Square struct {
    Side float32
}

func (s Square) Area() float32 {
    return s.Side * s.Side
}

Note that Side must be capitalized for it to be a public data member. Also note that its passed by value, in Go the style is to only pass by pointer if you intend to modify the struct.

square_test.go might look like this.

package square_test

import(
    "testing"
    "square"
    "github.com/stvp/assert"
)

func TestArea( t *testing.T ) {
    sq := square.Square{Side: 5}
    
    assert.Equal( t, sq.Area(), float32(25) )
}

Go does not come with any asserts. github.com/stvp/assert provides the basics and removes a lot of tedium. You can get it with go get github.com/stvp/assert.

Note that it is in package square_test to make this a blackbox test which can only use the public interface of square. If you wanted a glassbox/internal test, it would use package square and go in its own file like square_internal_test.go.

If you want a program that uses square, that would be in its own separate package directory. It would have a main.go with package main and import "square".

How To Write Go explains this in more detail.

huangapple
  • 本文由 发表于 2017年7月3日 18:17:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/44883077.html
匿名

发表评论

匿名网友

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

确定