Setting Up Emacs for Go Development on macOS
Tags: go
Published: 2024-06-09 15:05:41

**Introduction**

Emacs is a highly customizable text editor with powerful features for programming. In this guide, we’ll walk through installing Emacs on macOS, setting it up for Go development, and using it effectively.

_Step 1: Install Emacs_
First, ensure you have Emacs installed on your system. You can download it from GNU Emacs or use a package manager.

_Step 2: Install Go_
Make sure you have Go installed. You can download it from the official Go website.

_Step 3: Install go-mode_
go-mode is an Emacs major mode for editing Go code. You can install it via MELPA (Milkypostman’s Emacs Lisp Package Archive).

Enable MELPA in Emacs:
Add the following to your Emacs configuration file (usually ~/.emacs or ~/.emacs.d/init.el):

```
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
```

Install go-mode:
Open Emacs and run the following commands:

`M-x package-refresh-contents`
`M-x package-install RET go-mode RET`

_Step 4: Configure go-mode_
Add the following configurations to your Emacs configuration file to enable go-mode and some useful Go tools:

```
(require 'go-mode)

;; Set up Go-specific key bindings
(add-hook 'go-mode-hook
          (lambda ()
            (setq tab-width 4)
            (setq indent-tabs-mode 1)))

;; Enable auto-completion
(add-hook 'go-mode-hook 'company-mode)

;; Enable Flycheck for real-time syntax checking
(add-hook 'go-mode-hook 'flycheck-mode)

;; Enable automatic formatting on save
(add-hook 'before-save-hook 'gofmt-before-save)

;; Optional: set $GOPATH and $GOROOT if not set globally
(setenv "GOPATH" "/path/to/your/gopath")
(setenv "GOROOT" "/path/to/your/goroot")
```

_Step 5: Install company-mode for Auto-completion
company-mode is a text completion framework for Emacs._

Install company-mode:

`M-x package-install RET company RET`

_Step 6: Install flycheck for Syntax Checking_
flycheck provides real-time syntax checking.

Install flycheck:

`M-x package-install RET flycheck RET`

_Step 7: Install and Configure gopls (Go Language Server)_
gopls is the official Go language server, providing IDE features.

Install gopls:

Open terminal tehn, 

```
go install golang.org/x/tools/gopls@latest
```

Configure Emacs to use gopls:
Add the following to your Emacs configuration file:

```
(use-package lsp-mode
  :ensure t
  :commands (lsp lsp-deferred)
  :hook ((go-mode . lsp-deferred))
  :config
  (setq lsp-prefer-flymake nil))  ;; Use flycheck instead of flymake

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode)

(use-package company-lsp
  :ensure t
  :commands company-lsp)
```

_Step 8: Additional Tools_

To further enhance your Go development experience in Emacs, you might want to install additional tools:

magit for Git integration:


`M-x package-install RET magit RET`

projectile for project management:

`M-x package-install RET projectile RET`

Example Configuration
Here's an example of a complete Emacs configuration for Go development:

```
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; Install and configure go-mode
(use-package go-mode
  :ensure t
  :hook ((go-mode . lsp-deferred)
         (before-save . gofmt-before-save))
  :config
  (setq tab-width 4)
  (setq indent-tabs-mode 1))

;; Enable company-mode for auto-completion
(use-package company
  :ensure t
  :hook (go-mode . company-mode))

;; Enable flycheck for real-time syntax checking
(use-package flycheck
  :ensure t
  :hook (go-mode . flycheck-mode))

;; Configure lsp-mode and lsp-ui for Go
(use-package lsp-mode
  :ensure t
  :commands (lsp lsp-deferred)
  :config
  (setq lsp-prefer-flymake nil))

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode)

(use-package company-lsp
  :ensure t
  :commands company-lsp)

;; Optional: projectile for project management
(use-package projectile
  :ensure t
  :config
  (projectile-mode +1))

;; Optional: magit for git integration
(use-package magit
  :ensure t)
```
Combined code for all packages:

```
;; Initialize package sources
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; Ensure use-package is installed
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

;; Install and configure go-mode
(use-package go-mode
  :ensure t
  :hook ((go-mode . lsp-deferred)
         (before-save . gofmt-before-save))
  :config
  (setq tab-width 4)
  (setq indent-tabs-mode 1))

;; Enable company-mode for auto-completion
(use-package company
  :ensure t
  :hook (go-mode . company-mode))

;; Enable flycheck for real-time syntax checking
(use-package flycheck
  :ensure t
  :hook (go-mode . flycheck-mode))

;; Configure lsp-mode and lsp-ui for Go
(use-package lsp-mode
  :ensure t
  :commands (lsp lsp-deferred)
  :config
  (setq lsp-prefer-flymake nil))

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode)

(use-package company-lsp
  :ensure t
  :commands company-lsp)

;; Optional: projectile for project management
(use-package projectile
  :ensure t
  :config
  (projectile-mode +1))

;; Optional: magit for git integration
(use-package magit
  :ensure t)

;; Function to run the current Go file
(defun my-go-run ()
  "Run the current Go file."
  (interactive)
  (let ((compile-command (concat "go run " buffer-file-name)))
    (compile compile-command)))

;; Function to build the current Go project
(defun my-go-build ()
  "Build the current Go project."
  (interactive)
  (compile "go build"))

;; Function to test the current Go project
(defun my-go-test ()
  "Test the current Go project."
  (interactive)
  (compile "go test ./..."))

;; Add key bindings for Go commands
(add-hook 'go-mode-hook
          (lambda ()
            (local-set-key (kbd "C-c C-r") 'my-go-run)
            (local-set-key (kbd "C-c C-b") 'my-go-build)
            (local-set-key (kbd "C-c C-t") 'my-go-test)))

;; End of configuration
```

This setup should give you a powerful and efficient Go development environment in Emacs.

_Step 9: Using Emacs for Go Development_

**Creating a Simple Go Program**

Open Emacs

Create a New Go File:

Command:

`C-x C-f ~/go/src/hello/hello.go RET`
Add Go Code:


```
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
```
Save the File:

Command:

`C-x C-s`

Running the Go Program
You can run your Go program directly from Emacs using the key bindings set up in your configuration.

Run the Current Go File:

Command:
`C-c C-r`

Build the Current Go Project:

Command:
`C-c C-b`

Test the Current Go Project:

Command:
`C-c C-t`

_Extra: Clearing an Entire File in Emacs_

Clearing File Content

Open File:

Command:
`C-x C-f /path/to/yourfile RET`

Select All Text:

Command:
`C-x h`

Delete Selected Text:

Command:
`C-w`
Save the File:

Command:
`C-x C-s`

Using erase-buffer Command

Open File

Run erase-buffer:

Command:
`M-x erase-buffer RET`

Save the File:

Command:
`C-x C-s`

Split window:

`C-x 2 (horizontal split)`
`C-x 3 (vertical split)`

Conclusion
By following this guide, you have set up Emacs on macOS for Go development, including installing necessary packages, configuring Emacs, and using it to write, run, build, and test Go programs. Happy coding!