Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to hide scopes and variables in Go language

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces "how to hide the scope and variables in the Go language". In the daily operation, I believe that many people have doubts about the scope and how to hide the variables in the GE language. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts about "how to hide the scope and variables in the Go language". Next, please follow the editor to study!

Preface

Variables hidden in Go can be confusing, so let's try to figure it out.

Package mainimport ("fmt"io/ioutil"log") func main () {f, err: = ioutil.TempFile ("", ") if err! = nil {log.Fatal (err)} defer f.Close () if _, err: = f.Write ([] byte (" Hello World\ n ")) Err! = nil {log.Fatal (err)} else {fmt.Println ("All success")}}

Notice that we first created two variables from the TempFile function: F and err. Then we call Write to discard the number of bytes written. We have the function call it in the if statement. Let's compile, it works fine.

$go run main.goAll success

Now, the same code as the Write call outside if:

Package mainimport ("fmt"io/ioutil"log") func main () {f, err: = ioutil.TempFile ("", ") if err! = nil {log.Fatal (err)} defer f.Close () / / if _, err: = f.Write ([] byte (" Hello World\ n ")) Err! = nil {/ / log.Fatal (err) / /} else {/ / fmt.Println ("All success") / /} _ Err: = f.Write ([] byte ("Hello World\ n")) if err! = nil {log.Fatal (err)} else {fmt.Println ("All success")}}

Run the code:

$go run main.go# command-line-arguments./main.go:23:9: no new variables on left side of: =

So what happened?

Notice that we use: = to call Write, which means that we have created a new variable err. In the second example, it is obvious that err already exists, so we cannot redeclare it.

But why did it work for the first time? Because in Go, a variable is the local variable of its scope. In the first example, we actually hide err within the scope of if.

For example:

Package mainfunc main () {var err error _ = err var err error _ = err}

This will obviously fail, but if we limit the second err, it will work!

Package mainfunc main () {var err error _ = err {var err error _ = err}} package hiding

Consider the following code:

Package mainimport "fmt" func Debugf (fmt string, args... interface {}) {fmt.Printf (fmt, args...)}

At first, it looked good. We call Printf from the fmt package and pass it the fmt variable.

The fmt string in the function declaration actually hides the package and is now "just" a variable. The compiler complains that we need to use different variable names to save access to the fmt package.

Global variable

What needs to be considered is that a function is already a "subscope", which is a scope within the global scope. This means that any variable you declare in the function can hide something globally.

As we saw earlier, variables can map packages, and the concepts of global variables and functions are the same.

Type compulsion

Just as we can map a package with variables or functions, we can map a variable with any type of new variable. Shadow variables do not need to come from the same type. This example compiles well:

Package mainfunc main () {var a string _ = a {var an int _ = a} closure

When using embedded functions, scope is very important. Any undeclared variable used in the function is a reference to the upper scope. Well-known examples of using goroutine:

Package mainimport ("fmt"time") func main () {for _, elem: = range [] byte {'a', 'baked,' c'} {go func () {fmt.Printf ("% c\ n") Elem)} ()} time.Sleep (1e9) / / Sleeping to give time to the goroutines to be executed.}

Run the code:

$go run main.goccc

That's not what we really want. This is because the scope changes the elem referenced in the goroutine, so it will always show the last element in the short list.

To avoid this situation, there are two solutions:

1. Pass a variable to a function

Package mainimport ("fmt"time") func main () {for _, elem: = range [] byte {'await,' baked,'c'} {go func (char byte) {fmt.Printf ("% c\ n", char)} (elem)} time.Sleep (1e9)}

Running result:

$go run main.go

A

C

B

two。 Create a copy of the variable locally

Package mainimport ("fmt"time") func main () {for _, elem: = range [] byte {'await,' baked,'c'} {char: = elem go func () {fmt.Printf ("% c\ n", char)} ()} time.Sleep (1e9)}

By running this code, we can get the results we want:

When we pass a variable to a function, we actually send a copy of the variable to the function that receives it in character form. Because each goroutine has its own copy, there is no problem.

When we copy a variable, we create a new variable and assign the value of elem to it. We do this in each iteration, which means that for each step, we create a new variable that goroutine references. Each goroutine has a reference to a different variable, and it works fine.

Now that we know we can hide variables, why change the name? We can simply use the same name because it affects the upper scope:

Package mainimport ("fmt"time") func main () {for _, elem: = range [] byte {'a', 'baked,' c'} {go func (elem byte) {fmt.Printf ("% c\ n") Elem)} (elem)} time.Sleep (1e9)} package mainimport ("fmt"time") func main () {for _, elem: = range [] byte {'aqu,' b' 'c'} {elem: = elem go func () {fmt.Printf ("% c\ n", elem)} ()} time.Sleep (1e9)}

The same thing happens when we pass a variable to a function, and we pass a copy of the variable to the function, which gets it with the name elem and the correct value.

In this range, because the variable is obscured, we cannot affect the element from the upper scope, and any changes made will only be applied within this range.

When we copy the variable, it's the same as before: we create a new variable and assign the value of elem to it. In this case, the new variable happens to have the same name as another variable, but the idea remains the same: new variable + assignment. When we create a new variable with the same name in the scope, we effectively hide the variable while keeping its value.

Situation of: =

When: = is used with multiple return functions (or type assertions, channel reception, and mapping access), we can get three variables in two statements:

Package mainfunc main () {var iface interface {} str, ok: = iface. (string) if ok {println (str)} buf, ok: = iface. ([] byte) if ok {println (string (buf))}

In this case, the ok is not obscured, it is just overwritten. That's why ok can't change the type. However, doing so within the scope hides variables and allows for different types:

Package mainfunc main () {var m = map [string] interface {} elem, ok: = m ["test"] if ok {str, ok: = elem. (string) if ok {println (str)} Summary

Hiding can be useful, but you need to keep it in mind to avoid unexpected behavior. It is, of course, case-based, and it usually helps improve readability and security, but it can also be reduced.

In the case of goroutines, because it is a simple example, its shadow is more readable, but in more complex cases, it is best to use a different name to determine what you are modifying. On the other hand, however, it is a very powerful tool, especially for errors. Back to my first example:

Package mainimport ("io/ioutil"log") func main () {f, err: = ioutil.TempFile ("", ") if err! = nil {log.Fatal (err)} defer f.Close () if _, err: = f.Write ([] byte (" hello world\ n ")) Err! = nil {err = nil} / / err is still the one form TempFile}

In this case, hiding err in if ensures that previous errors will not be affected, and if you use the same code, we use = instead of: = in if, which does not hide variables but overwrites the wrong values.

At this point, the study of "how to hide scopes and variables in the Go language" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report