2

I have package a, which relies on an external package, language package:

package a

import (
    "fmt"

    "golang.org/x/text/language"
)

// Machine is a printer
type Machine struct{}

// Printer prints
type Printer interface {
    Print(lang language.Tag)
}

// Print prints the language
func (p *Machine) Print(l language.Tag) {
    fmt.Println(l.String())
}

For package a, I've run "dep init" and then "dep ensure".

In another package, I have a main.go file, which imports package a:

package main

import (
    "testing/a"

    "golang.org/x/text/language"
)

func main() {
    m := a.Machine{}
    m.Print(language.MustParse("en"))
}

I get an error:

cannot use "golang.org/x/text/language".MustParse("en") (type "golang.org/x/text/language".Tag) as type "testing/a/vendor/golang.org/x/text/language".Tag in argument to m.Print

If I put the main package in package a, it works fine. Why won't it work when calling from an external package?

Go version is 1.10.2

EDIT: i have full control over package a, so I can change the way I vendor things there. I can also upgrade my Go version if there is an easy fix with a newer Go version.

UPDATE: I've upgraded to Go 1.12.1 and have removed the existing vendor directory. I ran "go mod init" and "go mod vendor" for package a but still get the same error when I run main.go in package b.

cannot use "testing/b/vendor/golang.org/x/text/language".MustParse("en") (type "testing/b/vendor/golang.org/x/text/language".Tag) as type "testing/a/vendor/golang.org/x/text/language".Tag in argument to m.Print

If I try to import the vendored package directly from package a I get:

use of vendored package not allowed
Pallav Jha
  • 3,409
  • 3
  • 29
  • 52
user_78361084
  • 3,538
  • 22
  • 85
  • 147
  • 2
    You should definitely upgrade Go, since you're 2 versions behind and it's no longer supported. Use a vendoring tool to make sure the dependencies are properly flattened, or try using go modules (`go mod vendor` is also a good way to create a vendor directory) – JimB Mar 14 '19 at 21:31
  • 1
    Actually yeah, flattening the vendored dependencies would probably be better than directly importing a vendored-dependency-within-a-vendored-dependency, if you're willing to use those tools and if there aren't potential version conflicts. +1. – Jesse Amano Mar 14 '19 at 21:53
  • I've run "go mod init" and "go mod vendor" for package a but still get the same error when I run main.go in package b. – user_78361084 Mar 15 '19 at 00:26
  • 1
    Possible duplicate of [package's type cannot be used as the vendored package's type](https://stackoverflow.com/questions/38091816/packages-type-cannot-be-used-as-the-vendored-packages-type) – Jonathan Hall Mar 15 '19 at 09:57
  • Only vendor in the top-level project. You can either move to modules completely and not worry about vendoring, or use a tool which automatically flattens any nested vendor directories. – JimB Mar 15 '19 at 13:20
  • @JimB I moved to modules yet problem persists. Please see edit. – user_78361084 Mar 16 '19 at 13:58
  • The `testing/b` package you're using somehow still has a vendor directory. If you're no longer using `vendor` in there, you need to figure out where that directory is coming from. – JimB Mar 16 '19 at 14:03
  • @MarissaLevy I've updated the answer – Pallav Jha Mar 19 '19 at 06:51

1 Answers1

0

If the vendored copy of the dependencies are required to be used then the flag -mod=vendor is to be passed to go run

For example,

> tree
.
|-- a
|   `-- machine.go
`-- main.go

1 directory, 2 files

creating the module with the name testing because package a is imported as testing/a in main

> go mod init testing
go: creating new go.mod: module testing
> go mod vendor #this creates a vendor directory inside the project
go: finding golang.org/x/text/language latest
> tree -L 4
.
|-- a
|   `-- machine.go
|-- go.mod
|-- go.sum
|-- main.go
`-- vendor
    |-- golang.org
    |   `-- x
    |       `-- text
    `-- modules.txt

5 directories, 5 files  
> cat go.mod
module testing

go 1.12

require golang.org/x/text v0.3.0
> go run -mod=vendor main.go
en

Previous Answer

Below is my directory structure:

>tree /F
sample
│---go.mod
│---go.sum
│---main.go
│
└───a
    |---machine.go

Go Version

> go version
go version go1.12 windows/amd64

Module Creation

creating the module with the name testing because package a is imported as testing/a in main

> go mod init testing
go: creating new go.mod: module testing

Program execution

> go run main.go
go: finding golang.org/x/text/language latest
en
Pallav Jha
  • 3,409
  • 3
  • 29
  • 52
  • Any comment on how I could improve the answer would be helpful. – Pallav Jha Mar 15 '19 at 13:57
  • The question is about type mismatches when dependencies have vendored packages. This answer doesn't cover vendoring at all, and simply shows basic module usage. This might be the correct procedure in the end, but it at least needs to address the question, especially regarding why modules can still create the same situation. – JimB Mar 15 '19 at 14:55