Function not behaving properly when imported from an external file but fine when in the same file?

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

Function not behaving properly when imported from an external file but fine when in the same file?

问题

我正在解决 Project Euler 的问题,以便熟悉 Go 语言。这个问题不是关于 Project Euler 的,但是其中包含了一些 Project Euler 相关的代码,可能会透露出问题的挑战。"剧透警告"之类的,但现在你已经知道了。这是我的文件结构:

+ Project Euler
+-+ Go       <= GOPATH 设置在这里
  +-+ src
    +-+ util
    | +- util.go
    |
    +- 001.go
    +- 002.go
    ...
    +- 023.go

对于问题 23,我在 util.go 中添加了一个新的函数 SumOfDivisors(一个包含多个问题使用的各种方法的文件):

func GetPrimeFactors(val int) map[int]int {
	primes := map[int]int{}
	init := val
	num := 2
	for val > 1 {
		if (val % num) == 0 {
			if num == init {
				return nil
			}
			_, e := primes[num]
			if e {
				primes[num]++
			} else {
				primes[num] = 1
			}
			val /= num
		} else {
			num++
		}
	}
	return primes
}

func SumOfDivisors(val int) int {
	primes := GetPrimeFactors(val)
	if primes == nil {
		if val == 0 {
			return 0
		} else {
			return 1
		}
	}
	total := 1
	for k, v := range primes {
		if v > 1 {
			n := int((math.Pow(float64(k), float64(v+1)) - 1) / float64(k-1))
			total *= n
		} else {
			n := k + 1
			total *= n
		}
	}
	return total - val
}

为了测试这个方法,我在 023.go 中编写了以下基本的 Go 代码:

package main

import (
	"fmt"
	"util"
)

func main() {
	fmt.Println(util.SumOfDivisors(12))
}

我将 GOPATH 设置为 /Project Euler/Go,当我调用 go run 023.go 时,它似乎可以正常构建和运行。"似乎正常"的意思是没有错误、警告,除了我的代码之外没有其他输出。

屏幕上打印的是 1,而不是 16。我不认为这是一个逻辑问题,因为当我将 util.go 中的函数复制到 023.go 中(并修复对 GetPrimeFactors 的调用为 util.GetPrimeFactors),然后该函数就可以正常运行,并打印出应该打印的 16。我尝试在 util.SumOfDivisors 中添加 fmt.Println("TEST"),但它不会打印出这些语句,也没有出现错误或其他任何提示。如果我将 util.go 中的函数名称更改为其他任何名称,即使主函数是 023.go,它仍然可以构建和运行,并输出 1。它的行为真的很奇怪。

我的 util.go 文件中的其他函数似乎都可以正常调用。

我正在使用 Go 1.4.2 版本。可能是什么原因导致这种行为?这个函数在本地工作正常,但当移动到一个外部文件并导入时就不起作用了,为什么那个外部文件不能打印任何内容到屏幕上?而且所有这些问题都在构建时没有出现任何错误。

英文:

I'm working on Project Euler questions in order to get used to Go. The question is not about Project Euler, but there is Project Euler specific code in this question that might give away the challenge of a question. "Spoiler Alert" or whatever, but now you know. Here's my file structure:

+ Project Euler
+-+ Go       &lt;= GOPATH set here
  +-+ src
    +-+ util
    | +- util.go
    |
    +- 001.go
    +- 002.go
    ...
    +- 023.go

For problem 23, I'm adding a new function SumOfDivisors to util.go (a file with various methods used by multiple problems):

func GetPrimeFactors(val int) map[int]int {
	primes := map[int]int{}
	init := val
	num := 2
	for val &gt; 1 {
		if (val % num) == 0 {
			if num == init {
				return nil
			}
			_, e := primes[num]
			if e {
				primes[num]++
			} else {
				primes[num] = 1
			}
			val /= num
		} else {
			num++
		}
	}
	return primes
}

func SumOfDivisors(val int) int {
	primes := GetPrimeFactors(val)
	if primes == nil {
		if val == 0 {
			return 0
		} else {
			return 1
		}
	}
	total := 1
	for k, v := range primes {
		if v &gt; 1 {
			n := int((math.Pow(float64(k), float64(v+1)) - 1) / float64(k-1))
			total *= n
		} else {
			n := k + 1
			total *= n
		}
	}
	return total - val
}

In order to test this method, I wrote this basic Go inside 023.go:

package main

import (
	&quot;fmt&quot;
	&quot;util&quot;
)

func main() {
	fmt.Println(util.SumOfDivisors(12))
}

I have my GOPATH set to /Project Euler/Go and it builds and runs seemingly fine when I call go run 023.go. "Seemingly fine" meaning there are no errors, warnings, no output other than my code.

What is printing to the screen is 1 when it should be 16. I don't think it's a logic issue because when I copy the function from my util.go into 023.go (and fix the call to GetPrimeFactors to be util.GetPrimeFactors) then the function runs just fine and prints 16 just like it should. I've tried adding fmt.Println(&quot;TEST&quot;) to util.SumOfDivisors but it won't print those statements out and I don't get errors or anything else. If I change the name of the function in util.go to anything else, even if the main function is 023.go doesn't change, it still builds and runs outputting 1. It's really behaving weird.

Other functions in my util.go file seem to be called just fine.

I'm running Go 1.4.2. What might be causing this kind of behavior? The function works properly locally but not when moved to an external file that's imported and why can't that external file print anything to screen? All this while building just fine.

答案1

得分: 3

使用go build -a 023.go命令。

这将重新构建023.go所依赖的所有依赖项,并避免使用旧的编译版本。这是Go的一个优点,可以加快构建时间,但也可能导致这些问题。

正如我在评论中提到的,您一直在构建023.go,但可能没有运行go build util.go来更新023.go所依赖的util包。

-a选项将重新构建所有依赖项,您甚至可以添加-v以查看正在构建的内容和时间。

go build -a -v 023.go

或者

go run -a -v 023.go

运行、构建、清理和测试都有类似的标志。运行go help build获取更多信息。

英文:

Use go build -a 023.go

This will rebuild all dependencies that 023.go has and will avoid using old compiled versions of a package. This is one of go's strong suits that enables faster build times but it can cause these types of problems too.

As I mentioned in my comment, you kept building 023.go but you probably didn't run go build util.go to update the util package that 023.go depended on.

The -a option will rebuild all dependencies and you can even add -v to see what it is building and when.

go build -a -v 023.go

OR

go run -a -v 023.go

Run, build, clean, and test have similar flags. Run go help build for more info.

答案2

得分: 1

经过进一步的尝试,我发现存在一个/Project Euler/pkg文件夹,里面有一个名为util.a的文件。显然,我的代码的一个版本已经被构建,并且它的中间文件被缓存了。

删除pkg文件夹后,一切都恢复正常了。不匹配的函数名变成了编译器错误,然后(在修正函数名之后)我的util.go中的fmt.Println调用开始打印输出,我的答案变成了16。最后,这不是一个代码解决方案,而是一个缓存问题。

英文:

After a little more toying around, I've found that there exists a /Project Euler/pkg folder with a util.a inside it. Apparently a version of my code was built and it's intermediate files were cached.

After deleting the pkg folder, everything fell into place. The mismatched function names became a compiler error, then (after correcting the function names) my util.go fmt.Println calls were starting to print, and my answer was coming out as 16. In the end this wasn't a code solution, it was a caching problem.

huangapple
  • 本文由 发表于 2015年4月2日 06:35:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/29402046.html
匿名

发表评论

匿名网友

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

确定