-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,515 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
--- | ||
title: "Golang: Making Your Zero Values More Useful" | ||
date: 2022-01-16T15:04:40+08:00 | ||
author: "xiantang" | ||
# lastmod: | ||
tags: ["Chinese", "Golang"] | ||
categories: ["Golang"] | ||
images: | ||
- ./post/make_zero_value_useful.png | ||
description: Golang uses zero values to make your code more concise, including Golang json zero value, Golang map zero value, etc. | ||
draft: false | ||
--- | ||
|
||
|
||
<!-- | ||
* Always start with a sentence to synchronize the background and context | ||
* Comment-style writing quotes some big cows | ||
* More interesting jump links | ||
* Recommend some interesting links at the end of the article | ||
* Write the outline first, then the content --> | ||
|
||
> Make the zero value useful. | ||
--Go Proverbs | ||
|
||
Let's start with the Golang blog: [The zero value](https://go.dev/ref/spec#The_zero_value) | ||
> When memory is allocated to store a value, whether by declaration or by calling make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of this value is set to its type's zero value: false for booleans, 0 for integers, 0.0 for floats, `""` for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so, for example, if no value is specified, each element of a structure array will be zeroed. | ||
Setting a value to zero in this way provides a great guarantee for the safety and correctness of the program, and also ensures the readability and simplicity of the program. This is what Golang programmers call "Make the zero value useful". | ||
|
||
## Zero value cheat sheet | ||
|
||
| Type | Zero Value | | ||
| --- | --- | | ||
| bool | false | | ||
| int | 0 | | ||
| float | 0.0 | | ||
| string | "" | | ||
| pointer | nil | | ||
| function | nil | | ||
| slice | nil | | ||
| map | nil | | ||
| channel | nil | | ||
|
||
The initialization of zero values is recursive, so if no value is specified, each element of the structure array will be zeroed. | ||
|
||
```golang | ||
➜ gore --autoimport | ||
gore version 0.5.3 :help for help | ||
gore> var a [10]int | ||
gore> a | ||
[10]int{ | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
0, | ||
} | ||
``` | ||
|
||
The same is true for structures. We initialize a B structure that references A, and if no value is specified, each field of B will be zeroed. | ||
|
||
```golang | ||
➜ gore --autoimport | ||
gore version 0.5.3 :help for help | ||
gore> type A struct { i int; f float64 } | ||
gore> type B struct { i int; f float64; next A } | ||
gore> new(B) | ||
&main.B{ | ||
i: 0, | ||
f: 0.000000, | ||
next: main.A{ | ||
i: 0, | ||
f: 0.000000, | ||
}, | ||
} | ||
``` | ||
|
||
note: | ||
|
||
* new: new(T) returns a pointer to the `zero value` of the newly allocated T type. | ||
* The tool used is [gore](https://github.com/x-motemen/gore) | ||
|
||
## Usage of Zero Values | ||
|
||
The previous section has introduced what zero values are, here we will see how to use them. | ||
|
||
### sync.Mutex | ||
|
||
Here is an example of sync.Mutex, sync.Mutex is designed to be used directly through zero values without explicit initialization. | ||
|
||
```golang | ||
package main | ||
|
||
import "sync" | ||
|
||
type MyInt struct { | ||
mu sync.Mutex | ||
val int | ||
} | ||
|
||
func main() { | ||
var i MyInt | ||
|
||
// i.mu is usable without explicit initialisation. | ||
i.mu.Lock() | ||
i.val++ | ||
i.mu.Unlock() | ||
} | ||
``` | ||
|
||
Thanks to the characteristics of zero values, the two unexported variables inside Mutex will be initialized to zero values. So the zero value of sync.Mutex is an unlocked Mutex. | ||
|
||
```golang | ||
// A Mutex is a mutual exclusion lock. | ||
// The zero value for a Mutex is an unlocked mutex. | ||
// | ||
// A Mutex must not be copied after first use. | ||
type Mutex struct { | ||
state int32 | ||
sema uint32 | ||
} | ||
``` | ||
|
||
### bytes.Buffer | ||
|
||
Another example is bytes.Buffer, its zero value is an empty Buffer. | ||
|
||
```golang | ||
package main | ||
|
||
import "bytes" | ||
import "io" | ||
import "os" | ||
|
||
func main() { | ||
var b bytes.Buffer | ||
b.Write([]byte("go go go")) | ||
io.Copy(os.Stdout, &b) | ||
} | ||
``` | ||
|
||
### JSON omitempty | ||
|
||
JSON receivers also accept the `omitempty` flag, when the input field is a `zero value`, the receiver will ignore this field. | ||
|
||
```golang | ||
➜ gore --autoimport | ||
gore version 0.5.3 :help for help | ||
gore> type Person struct { | ||
..... Name string `json:"name"` | ||
..... Age int `json:"age"` | ||
..... Addr string `json:"addr,omitempty"` | ||
..... } | ||
gore> p1 := Person{ | ||
..... Name: "taoge", | ||
..... Age: 30, | ||
..... } | ||
main.Person{ | ||
Name: "taoge", | ||
Age: 30, | ||
Addr: "", | ||
} | ||
gore> data, err := json.Marshal(p1) | ||
... | ||
gore> string(data) | ||
"{\"name\":\"taoge\",\"age\":30}" | ||
``` | ||
|
||
### channel close | ||
|
||
In [Channel Axioms](https://dave.cheney.net/2014/03/19/channel-axioms), there is also a rule related to zero values, when the channel is closed, the <- operation on the closed channel always returns `zero value` immediately. | ||
|
||
```golang | ||
package main | ||
|
||
import "fmt" | ||
|
||
func main() { | ||
c := make(chan int, 3) | ||
c <- 1 | ||
c <- 2 | ||
c <- 3 | ||
close(c) | ||
for i := 0; i < 4; i++ { | ||
fmt.Printf("%d ", <-c) // prints 1 2 3 0 | ||
} | ||
} | ||
``` | ||
|
||
The correct way to solve the above problem is to use a for loop: | ||
|
||
```golang | ||
for v := range c { | ||
// do something with v | ||
} | ||
|
||
``` | ||
|
||
### Value not found for corresponding key in map | ||
|
||
For a map, if the corresponding key is not found, the map will return a zero value of the corresponding type. | ||
|
||
```golang | ||
➜ gore --autoimport | ||
gore version 0.5.3 :help for help | ||
gore> a := make(map[string]string) | ||
map[string]string{} | ||
gore> a["123"] = "456" | ||
"456" | ||
gore> a["000"] | ||
"" | ||
``` | ||
|
||
The solution to this problem is to return multiple values: | ||
|
||
```golang | ||
gore --autoimport | ||
gore version 0.5.3 :help for help | ||
gore> a := make(map[string]string) | ||
map[string]string{} | ||
gore> c,ok := a["000"] | ||
"" | ||
false | ||
``` | ||
|
||
For non-existent keys, the value of ok will become false. | ||
|
||
## Summary | ||
|
||
The above is some experience summary about `zero value`. I hope everyone can use the `zero value` better when designing code, and use the features provided by `zero value` to initialize some variables. | ||
|
||
## Related Links | ||
|
||
* [Golang zero value](https://dave.cheney.net/2013/01/19/what-is-the-zero-value-and-why-is-it-useful) | ||
* [《Channel Axioms》](https://dave.cheney.net/2014/03/19/channel-axioms) | ||
* [Go REPL](https://github.com/x-motemen/gore) | ||
|
||
## Article Recommendations | ||
|
||
Finally, I would like to share with you some good articles I have been reading recently. I wanted to send them in a weekly format, but because I read them in a scattered way, I put them at the end of each blog post, hoping everyone can gain something. | ||
|
||
* [Why we don't have children](https://shuxiao.wang/posts/why-no-new-baby/) Some thoughts about having children | ||
* [Detailed interpretation of the paper "The Tail At Scale"](https://blog.csdn.net/LuciferMS/article/details/122522964) | ||
* [Writing maintainable Go code](https://jogendra.dev/writing-maintainable-go-code) Many points resonate with me after practice. The code is written once, but it will be read hundreds of times, so writing maintainable code is very important. | ||
* [Advanced Golang concurrency programming talk](https://go.dev/blog/io2013-talk-concurrency) The sharer provides actual concurrency problems and then gives some of his own solutions. Very beneficial. | ||
* [pprof graphic explanation](https://github.com/google/pprof/blob/master/doc/README.md#interpreting-the-callgraph) Finally, I can read pprof. | ||
|
||
Sure, please provide the Markdown content you want to translate. I'll make sure to follow the rules you've outlined. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
--- | ||
title: "Using neovim as a PDE (Personalized Development Environment)" | ||
date: 2022-10-29T20:45:20+08:00 | ||
author: "xiantang" | ||
# lastmod: | ||
tags: ["neovim"] | ||
categories: ["neovim"] | ||
images: | ||
- ./post/neovim.png | ||
description: | ||
draft: false | ||
--- | ||
|
||
|
||
<!-- * Always start with a sentence, synchronizing background and context --> | ||
<!-- * What you can learn from this article --> | ||
<!-- * Comment-style writing quotes some big shots --> | ||
<!-- * More interesting jump links --> | ||
<!-- * Recommend some interesting links at the end of the article --> | ||
<!-- * Write the outline first, then the content -- --> | ||
|
||
This article will not tell you how to configure neovim step by step, but will tell you some "Tao" about PDE, not the specific practice of "Art". | ||
|
||
## Introduction to neovim and PDE | ||
|
||
Seeing TJ's YouTube introduced the use of neovim as a PDE, it was interesting, so I tried it myself, it felt good, so I recorded it. | ||
|
||
### What is neovim | ||
|
||
Neovim is a branch of vim, vim is a text editor, neovim is a branch of vim, its goal is to provide a better vim, not a substitute for vim. | ||
|
||
What's the difference between neovim and vim? | ||
The difference is that neovim has refactored vim's code, supports lua scripts as configuration language on the basis of compatible vimscipt. At the same time, neovim's community on Github is more active than vim's. Neovim has a more useful lsp server, you can understand neovim is a superset of vim. | ||
|
||
|
||
### What is PDE | ||
|
||
PDE is a personalized development environment, which means that on the basis of meeting basic development needs, users can script and customize their development environment, thereby improving user development experience and efficiency. | ||
|
||
|
||
As you continue to solve the pain points in your development environment, your development efficiency will get higher and higher, and your development experience will get better and better, this is the charm of PDE. | ||
|
||
You can also continue to learn new things from it, in this process, you will also get a sense of accomplishment. | ||
|
||
|
||
## Basic needs to be met | ||
|
||
|
||
Define the basic needs that your PDE needs to meet, such as: | ||
|
||
* Highlighting | ||
* lsp | ||
* Basic refactoring rename | ||
* Quick jump | ||
* lint | ||
* Code suggestion | ||
* Code snippet | ||
* Debugging | ||
* Quickly find recent files | ||
|
||
Because only by satisfying these basic needs can you ensure that you will not return to your old editor. Keep finding your own pain points on top of this, and then solve them, you will get faster and faster and master this tool more and more. | ||
|
||
## Personalized needs | ||
|
||
Sometimes I always have some interesting needs, let me just give an example: | ||
|
||
For example, I often modify multiple projects in vim at the same time, but NERDTreeFind in nerdtree will only find from the current tree, and the root directory of the tree is always wrong. My requirement is to find this file in the bookmarks of nerdtree, and the root directory is the first matched bookmark. | ||
|
||
![show off](https://user-images.githubusercontent.com/34479567/204140677-0c11c2c8-cca7-44d2-8971-12632e3f0874.gif) | ||
|
||
You can refer to my implementation: | ||
|
||
https://github.com/xiantang/nvim-conf/blob/dev/lua/nerdtree.lua | ||
|
||
Basically all the functions you want can be achieved by modifying lua, or by using nvim series plugins. | ||
|
||
1. For example, quickly call up a terminal or a note txt | ||
2. Add some custom snippets | ||
3. And so on... | ||
|
||
## Better configuration management | ||
|
||
In fact, when everyone uses neovim to make their own PDE, they will find that you can easily mess up your neovim, because there are many plugins in your configuration, and these plugins are often incompatible. So the following two points are crucial: | ||
|
||
1. Quickly roll back the configuration to a stable version | ||
2. Quickly find out which version introduced the problem | ||
|
||
### Use git as the configuration management of neovim | ||
|
||
This is actually very simple, you just need to put your configuration file in a git repository. | ||
|
||
You can use your most stable branch as the master, and then you usually modify it on the dev branch. When you want a function, you can modify it on the dev branch, and then use it for a while. When the function is stable, merge it into the master. | ||
|
||
If the stable version of the master branch has a problem, I recommend a god command of git, git-bisect. You can set a behavior error version and a historical behavior correct version. This command will use a binary method to help you find out which version introduced this problem. | ||
|
||
### Troubleshooting | ||
|
||
There are several main commands: | ||
|
||
`checkhealth` checks the health of your neovim, such as whether your neovim supports lua, whether it supports python, whether the plugin dependencies are successfully installed, etc. | ||
`nvim --startuptime` records the startup time of your neovim. You can use this to find out which plugin is slowing down your neovim startup. You can also use the Startuptime plugin to view your neovim startup time. | ||
`verbose <map type> <key>` displays detailed information about your key mapping, such as whether your key mapping is successful, whether there are conflicts, etc. | ||
`lua =vim.inspect(var)` prints the information of the variable you need. | ||
|
||
## No need to switch suddenly, you can use ideavim and then switch slowly | ||
|
||
If you are not very familiar with (neo)vim, I suggest you try running the vimtutor command first to learn the basic operations of vim. | ||
Then you can use vim shortcuts in jetbrains using ideavim, so you can slowly switch to neovim. | ||
Pure vim development is not achieved overnight, it takes some time to adapt, but I believe you will love it. | ||
|
||
## Don't blindly use other people's configurations directly | ||
|
||
In addition, neovim actually has many derivative distributions. My suggestion is that if you are not very familiar with neovim, do not directly use other people's configurations, because you may encounter many problems, but you may not be able to solve these problems yourself, so if you want to use it, try to build your own configuration from other people's Minimal templates. | ||
|
||
|
||
## Interesting things | ||
* Use firenvim as a browser editor to brush leetcode [twitter](https://twitter.com/GIA917229015/status/1573365264439480321) | ||
* Use grammarly as an English language server to check your grammar errors | ||
|
||
## END | ||
|
||
Your PDE is just the most suitable for your environment, this article does not provide the author's configuration, what suits me may not suit you. | ||
|
||
## References | ||
* [PDE: A different take on editing code](https://www.youtube.com/watch?v=QMVIJhC9Veg&t=836s&ab_channel=TJDeVries) | ||
* [nvim-lua-guide](https://github.com/nanotee/nvim-lua-guide) | ||
* [jdhao](https://jdhao.github.io/) | ||
|
||
Sure, please provide the Markdown content you want to translate. |
Oops, something went wrong.