Any smart method to get exp/html back after Go1? - go

I've installed the Go release version as root.
Go1 removed all exp/ code.
Is there smart method to get exp/* back after Go1?
(I mean how to install in my local GOPATH?)
[My Solution]
# pull from go repository to $HOME/repo/go
cd $HOME/repo
hg clone https://go.googlecode.com/hg/go
# make symbolic link to your GOPATH(eg. $HOME/go)
cd $HOME/go/src
ln -s $HOME/repo/go/src/pkg/exp .

The exp/html library was incomplete which is why it was removed for Go1.
However if you really want to use it then
go get code.google.com/p/go/src/pkg/exp/html
may install it back for you. If you want a slightly more complete html parser then you might checkout http://code.google.com/p/go-html-transform/ as well it has an html5 parser as well as a css selector based scraping and transformation library.
EDIT: Apparently trying to go get the package that way doesn't really work. It appears the only way to install this is to checkout the go source code and then install from source. This is actually a really quick an painless process if you want to go that route.

Building from source is the way to do this. When you do the hg update step though, note that since the exp tree is not tagged go1, that hg update release won't get it for you. Instead hg update weekly will get it, and is probably what you want.
Edit: Weekly releases were discontinued after Go 1, so hg update weekly will access increasingly stale code. A better strategy is hg update tip, then copy the exp directory or directories of interest somewhere and recompile it with whatever Go version you are using, Go 1.0.1, for example.

Note: with go 1.4 (Q4, 2014), the url for that exp package will change (again):
code.google.com/p/go.exp => golang.org/x/exp
That means now:
go get golang.org/x/exp
See "Go 1.4 subrepo renaming".
Regarding the html package, it is in net/html, so this will become (as commented by andybalholm):
go get golang.org/x/net/html

The exp packages have been moved to different repositories now, to make them easier to install. Now you can install the former exp/html with go get "golang.org/x/net/html".

This answer is outdated.
This is covered in the golang wiki:
https://code.google.com/p/go-wiki/wiki/InstallingExp
% cd $GOPATH/src
% hg clone https://code.google.com/p/go go-exp
requesting all changes
adding changesets
adding manifests
adding file changes
added 13323 changesets with 50185 changes to 7251 files (+5 heads)
updating to branch default
3464 files updated, 0 files merged, 0 files removed, 0 files unresolved
% mv go-exp/src/pkg/exp .
% rm -rf go-exp
% go install exp/...
Then, to use it:
import "exp/proxy"
I tried this a few months ago and it worked pretty well. Also, when I ran go install ... I limited it to only the package I was interested in: go install exp/html (if I recall, correctly).

Related

go get installation from a local fork

I am trying to install a go package from a local directory (basically I checked out and existing package and applied a pending pull request).
$ # Both commands give a similar output
$ go get -u file:///Users/me/workspaces/go/somepackage
$ go get -u /Users/me/workspaces/go/somepackage
unrecognized import path "[...]" (import path does not begin with hostname)
Since go get is downloading then installing, I tried:
$ go install /Users/me/workspaces/go/somepackage
[] cannot import absolute path
Any experienced go user could give a hand?
If you just want to use a different branch (your PR branch), you can continue using the original import path.
Go get the original package first.
Go into the downloaded package in your local file system cd $GOPATH/pkg/<package directory>
From your local package cache, switch to the branch you want to pull from. git checkout <PR branch>
Now go get -u <package>
If the package is available locally, go get update will just pull the latest code from the branch your local package is checked out to.
As far as I know you can't do this with go get, bur you can copy the directory in to GOPATH manually. If you forked example.com/somepackage then copy /Users/me/workspaces/go/somepackage to ~/go/src/example.com/somepackage or ./vendor/example.com/somepackage.
That being said, the best solution is usually to host the forked code somewhere, and then use that import path. Decency tools such as dep and modules support fetching a different origin for packages.
I could be wrong and maybe there is a workaround exists
Go documentantion on cmd/go/#hdr-Remote_import_paths says:
The supported version control systems are:
Bazaar .bzr
Fossil .fossil
Git .git
Mercurial .hg
Subversion .svn
And a later:
For example,
import "example.org/pkg/foo"
will result in the following requests:
https://example.org/pkg/foo?go-get=1 (preferred)
http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure)
So I suppose that go get never looks in filesystem repos.
Need to investigate source code of go get to be sure.
I will be glad if someone will prove that I am incorrect in this question.
UPDATE
Maybe I'm mistaken but I suppose that all abilities of go get to work with VCSs are here: https://github.com/golang/go/blob/master/src/cmd/go/internal/get/vcs.go
And I don't see here a possibility to work with git local repos.

Issues with 'go build' on forked repository

I build a binary file for a GitHub repo (go code), which works fine. no issues.
I forked that repo, and modified a single line in the HTML file that has nothing to do with GO code, built the binary file for the new forked repo but the binary it generates refers to the original repo code, can't understand why.
I even cleaned all the code using go clean -i all command and manually removed all the installed code, binary files from $home/go/bin and the repo directory, but it still refers to the original repo code instead of new forked code.
Based on the solution suggested by Tobias, I performed the following steps:
After that, I executed go build in that repo directory, but the new binary file still refers to the old code. I even removed the old binary file and generated a new one.
That's a common problem in go. The references system in "location based" so it searches for these files in the "correct" path. Idk if go modules fix this issue, but atleast when not using go modules you'll have to work around it.
You can solve it by
Solution 1
Download the original repository you forked by:
go get http://github.com/awesome-org/tool
Add your fork as remote
git remote add awesome-you-fork http://github.com/awesome-you/tool
You'll have to make changes in the folder of the original downloaded repo and Push and Pull to/from your fork.
git pull --rebase awesome-you-fork
git push awesome-you-fork
Solution 2
Work around go get:
You create the path the original repo would have, but clone your own fork into it. That way you can push & pull to your fork. That may be the better solution
cd $GOPATH
mkdir -p {src,bin,pkg}
mkdir -p src/github.com/awesome-org/
cd src/github.com/awesome-org/
git clone git#github.com:awesome-you/tool.git # OR: git clone https://github.com/awesome-you/tool.git
cd tool/
go get ./...
These Solutions were found here: http://code.openark.org/blog/development/forking-golang-repositories-on-github-and-managing-the-import-path
The problem with a forked copy of a go packages is when the package is really multiple go packages in one repo, the import statements refer to original base repo, ie: github.com/orig/repo.
This is not an issue for repos with only one go package as it never refers to itself.
But if it has multiple, ie: package github.com/orig/repo/A imports github.com/orig/repo/B
And then you fork it as: github.com/fork/repo
Then when the go compiler sees import "github.com/orig/repo/B" in the source, it goes to download the original version and not your fork.
Fortunately, go modules solves this.
Basically, create a go.mod at the top of your forked repo and add:
module github.com/orig/repo
then, the go compiler will assume that you are "orig/repo" regardless of where you actually are checked out from.
so, when orig/repo/A imports orig/repo/B, it will look locally.
If there are other imports you need to override that are outside the main forked repo, you can also force dependencies to come from another place using replace
SOLVED
At first I thought it was problem with a FORK (which is a common problem experienced with fork of Go language repo's), but it turns out, it was Repo specific problem.
One of the dependent libraries had to be reinstalled for the forked repo to work, which was not mentioned in the Original repo docs.
Finally, this link helped: https://github.com/inconshreveable/ngrok/issues/181#issuecomment-65646229, the problem was not generic but repo specific
I followed the below steps from above link to resolve the dependency on go-bindata
go get github.com/jteeuwen/go-bindata
cd $GOPATH/src/github.com/jteeuwen/go-bindata/go-bindata
go build

Library dependencies in Go

I've created a library/package in Go and the consensus was that only applications include a vendor folder in their project and libraries don't.
So now I included my package in another (govendor'ed) project and everything worked fine, untill it got to Jenkins and it had to use its local resources, where 2 of the dependencies were missing.
My project readme says all you need to do is go get my project and you're done. But that's not the case in case you're using govendoring.
What should be the approach for my library? Can this be solved, or is this 'problem' just something the end-user has to solve because they use govendor?
This is more of an opinion question I guess, however I'll share what I use.
I use git subtree for vendoring sub repos in my tree then add a //go:generate line to update it later on, for example:
➜ git subtree add --prefix vendor/xxx/yyy/zzz https://github.com/xxx/yyy/zzz master --squash
Then add //go:generate git subtree pull --prefix vendor/xxx/yyy/zzz https://github.com/xxx/yyy/zzz master --squash to one of my library files.
And just run go generate before I make release.
That solves the vendoring issue without the need of any external tools.
Live example: https://github.com/OneOfOne/xxhash/blob/master/xxhash_cgo.go

How should I use vendor in Go 1.6?

First I have read this answer: Vendoring in Go 1.6, then I use it as my example.
My gopath is GOPATH="/Users/thinkerou/xyz/", and the follow like:
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou$ pwd
/Users/baidu/xyz/src/ou
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou$ ls
main.go vendor
Now, I use go get, then becomes this:
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou$ ls
main.go vendor
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou$ cd vendor/
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou/vendor$ ls
vendor.json
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/ou/vendor$ cd ../..
thinkerou#MacBook-Pro-thinkerou:~/xyz/src$ ls
github.com ou
thinkerou#MacBook-Pro-thinkerou:~/xyz/src$ cd github.com/
thinkerou#MacBook-Pro-thinkerou:~/xyz/src/github.com$ ls
zenazn
vendor.json is this:
{
"comment": "",
"package": [
{
"path": "github.com/zenazn/goji"
}
]
}
then, I should use what commands? why have no use vendor? My go version is 1.6.2.
With Go1.6, vendoring is built in as you read. What does this mean? Only one thing to keep in mind:
When using the go tools such as go build or go run, they first check to see if the dependencies are located in ./vendor/. If so, use it. If not, revert to the $GOPATH/src/ directory.
The actual "lookup paths" in Go 1.6 are, in order:
./vendor/github.com/zenazn/goji
$GOPATH/src/github.com/zenazn/goji
$GOROOT/src/github.com/zenazn/goji
With that said, go get will continue to install into you $GOPATH/src; and, go install will install into $GOPATH/bin for binaries or $GOPATH/pkg for package caching.
So, how do I use ./vendor?!?!
Hehe, armed with the knowledge above, it's pretty simple:
mkdir -p $GOPATH/src/ou/vendor/github.com/zenazn/goji
cp -r $GOPATH/src/github.com/zenazn/goji/ $GOPATH/src/ou/vendor/github.com/zenazn/goji
In short, to use vendoring, you copy the files using the same github.com/zenazn/goji full path, into your vendor director.
Now, the go build/install/run tooling will see and use your vendor folder.
An easier way instead of copying everything manually
Instead of finding and copying all 25+ vendor items, managing their versions, updating other projects etc... It would be better to use a dependency management tool. There are many out there and a little googling will point to you several.
Let me mention two that works with the vendor folder and doesn't fight you:
godep
govendor
In short, these tools will inspect your ou code, find the remote dependencies, and copy them from your $GOPATH/src to your $GOPATH/src/ou/vendor directory (actually, whatever current directory you are in when you run them).
For example, say you have all of your dependencies installed and working normally in your $GOPATH/src/ou/ project using the normal GOPATH/src/github installation of your dependencies. Your project runs and your tests validate everything is working with the exact version of the repos you have. With Godep as an example, you'd run this from your project root folder $GOPATH/src/ou/:
godep save ./...
This would copy all dependencies your project uses into your ./vendor folder.
Godep is by far and large the most popular. They have their own Slack channel on the Gopher Slack group. And, it's the one I use on my teams.
Govendor is another alternative I read has a nice sync feature. I haven't used it though.
Over Usage of Dependency Management Tool
This is purely opinion, and I'm sure haters will downvote... But as I need to finish my blog post on the subject, let me mention here that most people worry too much about depdency management in Go.
Yes, there is a need to lock in a repo to a version you depend on so you can ensure your system builds in production. Yes there is a need to ensure no breaking changes to a way a dependency is interrupting something.
Use dependency management for those, absolutely.
But, there is overuse of simple projects that lock in huge amounts of dependencies when in reality...
You may only need to lock in only 1 dependencies; otherwise, you want the latest version of MySQL drivers and test assertion frameworks for bug fixes.
This is where using the ./vendor/ folder apart from dependency managrment tools can really shine: you'd only need to copy that repo that need you lock in.
You selectively pick the one misbehaving repo and put it into your ./vendor/ folder. By doing this, you are telling your consumers:
Hey, this one repo needs to be held back at this revision. All others are fine and use the latest of those and update often with go get -u ./...; but, this one failed with newer versions so don't upgrade this one repo.
But if blanketly saving all your dependencies with a dependency management tool, you are basically telling your consumers:
There may or may not be a problem with one or more repos out of the 20 in the vendor folder. You may or may not be able to update them. You may or may not be able to get the latest MySQL driver. We simply don't know which may or may not be causing problems and just locked in something that worked at the time that I ran godep save. So yeah, upgrade at your own risk.
Personally, I have ran into this several times. A dependency was updated with a breaking change, and we have dozens of repos dependent on it. Vendoring just that one repo in /vendor allows us to use that one version of dependency, while go get ./... continues to run normally for all other repos to get the latest. We run with the latest bug fixes in PSQL and MySQL and others (there are constant fixes for these!) and so on.

How do I import a specific version of a package using go get?

coming from a Node environment I used to install a specific version of a vendor lib into the project folder (node_modules) by telling npm to install that version of that lib from the package.json or even directly from the console, like so:
$ npm install express#4.0.0
Then I used to import that version of that package in my project just with:
var express = require('express');
Now, I want to do the same thing with go. How can I do that?
Is it possible to install a specific version of a package? If so, using a centralized $GOPATH, how can I import one version instead of another?
I would do something like this:
$ go get github.com/wilk/uuid#0.0.1
$ go get github.com/wilk/uuid#0.0.2
But then, how can I make a difference during the import?
Go 1.11 will have a feature called go modules and you can simply add a dependency with a version. Follow these steps:
go mod init .
go mod edit -require github.com/wilk/uuid#0.0.1
go get -v -t ./...
go build
go install
Here's more info on that topic - https://github.com/golang/go/wiki/Modules
Really surprised nobody has mentioned gopkg.in.
gopkg.in is a service that provides a wrapper (redirect) that lets you express versions as repo urls, without actually creating repos. E.g. gopkg.in/yaml.v1 vs gopkg.in/yaml.v2, even though they both live at https://github.com/go-yaml/yaml
gopkg.in/yaml.v1 redirects to https://github.com/go-yaml/yaml/tree/v1
gopkg.in/yaml.v2 redirects to https://github.com/go-yaml/yaml/tree/v2
This isn't perfect if the author is not following proper versioning practices (by incrementing the version number when breaking backwards compatibility), but it does work with branches and tags.
A little cheat sheet on module queries.
To check all existing versions: e.g. go list -m -versions github.com/gorilla/mux
Specific version #v1.2.8
Specific commit #c783230
Specific branch #master
Version prefix #v2
Comparison #>=2.1.5
Latest #latest
E.g. go get github.com/gorilla/mux#v1.7.4
You can use git checkout to get an specific version and build your program using this version.
Example:
export GOPATH=~/
go get github.com/whateveruser/whateverrepo
cd ~/src/github.com/whateveruser/whateverrepo
git tag -l
# supose tag v0.0.2 is correct version
git checkout tags/v0.0.2
go run whateverpackage/main.go
Glide is a really elegant package management for Go especially if you come from Node's npm or Rust's cargo.
It behaves closely to Godep's new vendor feature in 1.6 but is way more easier. Your dependencies and versions are "locked" inside your projectdir/vendor directory without relying on GOPATH.
Install with brew (OS X)
$ brew install glide
Init the glide.yaml file (akin to package.json). This also grabs the existing imported packages in your project from GOPATH and copy then to the project's vendor/ directory.
$ glide init
Get new packages
$ glide get vcs/namespace/package
Update and lock the packages' versions. This creates glide.lock file in your project directory to lock the versions.
$ glide up
I tried glide and been happily using it for my current project.
Nowadays you can just use go get for it. You can fetch your dependency by the version tag, branch or even the commit.
go get github.com/someone/some_module#master
go get github.com/someone/some_module#v1.1.0
go get github.com/someone/some_module#commit_hash
more details here - How to point Go module dependency in go.mod to a latest commit in a repo?
Go get will also install the binary, like it says in the documentation -
Get downloads the packages named by the import paths, along with their dependencies. It then installs the named packages, like 'go install'.
(from https://golang.org/cmd/go/)
Update 18-11-23: From Go 1.11 mod is official experiment. Please see #krish answer.
Update 19-01-01: From Go 1.12 mod is still official experiment.
Starting in Go 1.13, module mode will be the default for all development.
Update 19-10-17: From Go 1.13 mod is official package manager.
https://blog.golang.org/using-go-modules
Old answer:
You can set version by offical dep
dep ensure --add github.com/gorilla/websocket#1.2.0
From Go 1.5 there's the "vendor experiment" that helps you manage dependencies. As of Go 1.6 this is no longer an experiment. Theres also some other options on the Go wiki..
Edit: as mentioned in this answer gopkg.in is a good option for pinning github-depdencies pre-1.5.
dep is the official experiment for dependency management for Go language. It requires Go 1.8 or newer to compile.
To start managing dependencies using dep, run the following command from your project's root directory:
dep init
After execution two files will be generated: Gopkg.toml ("manifest"), Gopkg.lock and necessary packages will be downloaded into vendor directory.
Let's assume that you have the project which uses github.com/gorilla/websocket package. dep will generate following files:
Gopkg.toml
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/gorilla/websocket"
version = "1.2.0"
Gopkg.lock
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "941e8dbe52e16e8a7dff4068b7ba53ae69a5748b29fbf2bcb5df3a063ac52261"
solver-name = "gps-cdcl"
solver-version = 1
There are commands which help you to update/delete/etc packages, please find more info on official github repo of dep (dependency management tool for Go).
go get is the Go package manager. It works in a completely decentralized way and how package discovery still possible without a central package hosting repository.
Besides locating and downloading packages, the other big role of a package manager is handling multiple versions of the same package. Go takes the most minimal and pragmatic approach of any package manager. There is no such thing as multiple versions of a Go package.
go get always pulls from the HEAD of the default branch in the repository. Always. This has two important implications:
As a package author, you must adhere to the stable HEAD philosophy. Your default branch must always be the stable, released version of your package. You must do work in feature branches and only merge when ready to release.
New major versions of your package must have their own repository. Put simply, each major version of your package (following semantic versioning) would have its own repository and thus its own import path.
e.g. github.com/jpoehls/gophermail-v1 and github.com/jpoehls/gophermail-v2.
As someone building an application in Go, the above philosophy really doesn't have a downside. Every import path is a stable API. There are no version numbers to worry about. Awesome!
For more details : http://zduck.com/2014/go-and-package-versioning/
The approach I've found workable is git's submodule system. Using that you can submodule in a given version of the code and upgrading/downgrading is explicit and recorded - never haphazard.
The folder structure I've taken with this is:
+ myproject
++ src
+++ myproject
+++ github.com
++++ submoduled_project of some kind.
That worked for me
GO111MODULE=on go get -u github.com/segmentio/aws-okta#v0.22.1
There's a go edit -replace command to append a specific commit (even from another forked repository) on top of the current version of a package.
What's cool about this option, is that you don't need to know the exact pseudo version beforehand, just the commit hash id.
For example, I'm using the stable version of package "github.com/onsi/ginkgo v1.8.0".
Now I want - without modifying this line of required package in go.mod - to append a patch from my fork, on top of the ginkgo version:
$ GO111MODULE="on" go mod edit -replace=github.com/onsi/ginkgo=github.com/manosnoam/ginkgo#d6423c2
After the first time you build or test your module, GO will try to pull the new version, and then generate the "replace" line with the correct pseudo version. For example in my case, it will add on the bottom of go.mod:
replace github.com/onsi/ginkgo => github.com/manosnoam/ginkgo v0.0.0-20190902135631-1995eead7451
It might be useful.
Just type this into your command prompt while cd your/package/src/
go get github.com/go-gl/mathgl#v1.0.0
You get specific revision of package in question right into your source code, ready to use in import statement.
The current way to do this is to use go install
https://golang.org/doc/go-get-install-deprecation
Starting in Go 1.17, installing executables with go get is deprecated. go install may be used instead.
go install github.com/someone/some_module
Specific version
go install github.com/someone/some_module#v1.1.0
Specific commit
go install github.com/someone/some_module#commit_hash

Resources