{"id":134999,"date":"2021-05-05T16:59:37","date_gmt":"2021-05-05T15:59:37","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=go&#038;p=134999"},"modified":"2021-05-06T07:28:14","modified_gmt":"2021-05-06T06:28:14","slug":"compile-and-run-go-code-using-wsl-2-and-goland","status":"publish","type":"go","link":"https:\/\/blog.jetbrains.com\/en\/go\/2021\/05\/05\/compile-and-run-go-code-using-wsl-2-and-goland","title":{"rendered":"Compile and run Go code using WSL 2 and GoLand"},"content":{"rendered":"<p>Today, I&#8217;m happy to introduce our latest feature to you to use Windows Subsystem for Linux version 2 (WSL 2, or simply WSL) to run or test Go applications seamlessly.<\/p>\n<p>This feature is called <code>Run Targets<\/code> and supports <em>WSL 2<\/em>, <em>Docker<\/em>, and <em>SSH remotes<\/em>.<\/p>\n<p>If you&#8217;d like to learn more about these, <a href=\"https:\/\/blog.jetbrains.com\/en\/go\/2021\/04\/29\/what-are-run-targets-and-how-to-run-code-anywhere\">the overview article of this feature<\/a>, explaining it in more detail, should come in handy.<\/p>\n<p>In this article, I&#8217;ll focus on the <em>WSL 2<\/em> side of this feature. If you wish to use other targets, you can check the article covering the <a href=\"https:\/\/blog.jetbrains.com\/en\/go\/2021\/04\/30\/how-to-use-docker-to-compile-go-from-goland\">Docker target<\/a>.<\/p>\n<p>If you&#8217;d prefer a video version of this article, then please head to YouTube:<\/p>\n<p><iframe loading=\"lazy\" title=\"Compile and Run Go Code Using WSL 2 and GoLand\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/Xk8_jw94Ikc?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>Run Targets for WSL 2 in action<\/h2>\n<p>For this article, I&#8217;ll reuse most of the code that we&#8217;ve seen in the Docker tutorial \u2013 with the change that we are now checking for the WSL instead of a Docker environment.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net\/http\"\n\t\"os\/exec\"\n\t\"runtime\"\n\t\"strings\"\n)\n\nfunc homeHandler(w http.ResponseWriter, r *http.Request) {\n\tmyOS, myArch := runtime.GOOS, runtime.GOARCH\n\tinWSL := \"outside\"\n\tcmd := exec.Command(\"uname\", \"-a\")\n\tif output, err := cmd.Output(); err == nil {\n\t\tif strings.Contains(strings.ToLower(string(output)), \"microsoft\") {\n\t\t\tinWSL = \"inside\"\n\t\t}\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"text\/plain\")\n\tw.WriteHeader(http.StatusOK)\n\n\t_, _ = fmt.Fprintf(w, \"Hello, %s!\\n\", r.UserAgent())\n\t_, _ = fmt.Fprintf(w, \"I'm running on %s\/%s.\\n\", myOS, myArch)\n\t_, _ = fmt.Fprintf(w, \"I'm running %s of WSL.\\n\", inWSL)\n}\n\nfunc main() {\n\thttp.HandleFunc(\"\/\", homeHandler)\n\n\terr := http.ListenAndServe(\":38000\", nil)\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n}\n<\/pre>\n<h2 id=\"the-wsl-environment\">Enter the WSL 2 environment<\/h2>\n<p>With the WSL becoming more popular among developers, let&#8217;s see how we can use it for our applications.<\/p>\n<p>We first need to create a new run target.<\/p>\n<p>Head over to <code>Run | Manage Targets... | + | WSL<\/code>.<\/p>\n<p>If you have different Linux distributions installed, you can choose which one to use. Creating multiple targets is possible, which means you can create one for each of these Linux distributions.<\/p>\n<p>After the IDE performs the environment&#8217;s introspection, you can review the settings it detected and, if needed, adjust where the <code>go<\/code> binary is, what the <code>GOPATH<\/code> is, and what version of Go is in use.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" style=\"border: 1px solid #AAAAAA;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/04\/2-Create-WSL-Run-Target-optimized.png\" alt=\"Create WSL Run Target\" data-gif-src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/GoLand\/Run Targets - WSL\/2 - Create WSL Run Target - optimized.gif\" width=\"750\" height=\"421\"><\/p>\n<p>We can either edit the existing run configuration or create a new one to use the newly created target.<\/p>\n<p>Let&#8217;s reuse our existing run configuration and change the <code>Run on<\/code> field from the <code>Local machine<\/code> to the new WSL target.<\/p>\n<p>We can also change the working directory, if needed, to ensure that our application will start from the expected place.<\/p>\n<p>All that&#8217;s left to do is confirm our changes with the <code>OK<\/code> button and rerun the configuration.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" style=\"border: 1px solid #AAAAAA;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/04\/3-Use-the-WSL-Run-Target-in-the-Run-Configuration-optimized.png\" alt=\"Use the WSL Run Target in the Run Configuration\" data-gif-src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/GoLand\/Run Targets - WSL\/3 - Use the WSL Run Target in the Run Configuration - optimized.gif\" width=\"750\" height=\"421\"><\/p>\n<p>That&#8217;s it! Our application now works inside our WSL 2 environment.<\/p>\n<h2 id=\"debugging-a-go-application-using-wsl\">Debugging a Go application using WSL<\/h2>\n<p>Running is not the only option. We can also use the debugger to investigate what our application is doing at runtime.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" style=\"border: 1px solid #AAAAAA;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/04\/4-Debug-under-WSL-optimized.png\" alt=\"Debug under WSL\" data-gif-src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/GoLand\/Run Targets - WSL\/4 - Debug under WSL - optimized.gif\" width=\"750\" height=\"421\"><\/p>\n<h2 id=\"running-go-tests-and-benchmarks-in-wsl\">Running Go tests and benchmarks in WSL<\/h2>\n<p>Besides applications, you can run tests and benchmarks configurations using this feature.<\/p>\n<p>As an example, let&#8217;s create a new Go Test configuration and set the <code>Run on<\/code> field to the same WSL configuration as our application.<\/p>\n<p>Then, we need to launch our test, and it will run against the WSL environment.<\/p>\n<p>Tests with coverage or profiling with benchmarks work similarly.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" style=\"border: 1px solid #AAAAAA;\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/04\/5-Launch-Test-with-Run-Target-and-Coverage-optimized.png\" alt=\"Launch Test with Run Target and Coverage\" data-gif-src=\"https:\/\/resources.jetbrains.com\/storage\/products\/blog\/wp-content\/uploads\/GoLand\/Run Targets - WSL\/5 - Launch Test with Run Target and Coverage - optimized.gif\" width=\"750\" height=\"421\"><\/p>\n<h2 id=\"limitations\">Limitations:<\/h2>\n<p>There are a couple of limitations that you need to consider before using this feature.<\/p>\n<p>The source code has to be inside the Windows native side of the OS rather than under WSL 2. Otherwise, the IDE won&#8217;t be able to process any dependencies present in the code correctly.<br \/>\nThe Go SDK must be installed on Windows too, not just inside WSL 2, as the IDE cannot use the WSL 2 Go SDK.<\/p>\n<p>And that&#8217;s for today. We learned how to use WSL transparently to run our applications, tests, and benchmarks.<\/p>\n<p>Please keep in mind that this feature is still in its early days. We&#8217;d like to hear from you about any improvements we can make to transform this feature into another tool in your toolbelt.<\/p>\n<p>You can reach out to us by commenting below this post, raise an issue on <a href=\"https:\/\/youtrack.jetbrains.com\/issues\/Go\" target=\"_blank\" rel=\"noopener\">our tracker<\/a>, ping us on <a href=\"https:\/\/app.slack.com\/client\/T029RQSE6\/C3FJ8M2PN\" target=\"_blank\" rel=\"noopener\">Gophers Slack in the #goland<\/a> channel, or via <a href=\"https:\/\/twitter.com\/GoLandIDE\" target=\"_blank\" rel=\"noopener\">@GoLandIDE on Twitter<\/a>.<\/p>\n","protected":false},"author":828,"featured_media":0,"comment_status":"closed","ping_status":"closed","template":"","categories":[808,4221,2347],"tags":[6412,91,1038,6453,1303,2676],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/go\/134999"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/go"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/types\/go"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/users\/828"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/comments?post=134999"}],"version-history":[{"count":8,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/go\/134999\/revisions"}],"predecessor-version":[{"id":141257,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/go\/134999\/revisions\/141257"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media?parent=134999"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/categories?post=134999"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/tags?post=134999"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/cross-post-tag?post=134999"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}