Basic Calculator: How to script a function for deleting digits one by one? (GDScript) - button

How am I supposed to code a button that deletes digits in a basic calculator one by one?
Heres my script so far: https://pastebin.com/xLj2iCHU
func _on_BDeleteDigit_pressed():
var numberAdded
var numberBefore = $NumberStuffs.get_text()
numberAdded = numberAdded.length() - 1
numberAdded[numberBefore]=("")
$Outputlabel.set_text(str(numberAdded))
This is also the error when the delete button is pressed:
https://i.stack.imgur.com/8OJTI.png

Explaining the error
I'll start with the error. It says
Nonexistent function 'length' in base 'Nil'
The error is telling you that you are trying call a function called length on something that is Nil, but Nil does not have a function called length.
The problem is that you are trying to call something on Nil. What are you trying to call? length. So where is that? That is here:
numberAdded = numberAdded.length() - 1
So, numberAdded is Nil. The next question is why. So, let us see where numberAdded got its value…
So you declare it here:
var numberAdded
Then we have this line that has nothing to do with it:
var numberBefore = $NumberStuffs.get_text()
And then the line with the error:
numberAdded = numberAdded.length() - 1
What did you expect numberAdded.length() to be, if numberAdded does not have a value? Of course that is an error.
By the way, the code suggests that you expected numberAdded to be, well, a number. Which makes me wonder what you expected from this:
numberAdded[numberBefore]=("")
Yes you can do the inverted indexing thing in C or C++, because it is just adding pointers. But not GDScript, you don't.
I suspect that using types would help you. For example declare numberAdded to be an integer like this: var numberAdded:int. Yes, GDScript has types, use them.
How to delete the last character
Let me take as reference how you add a digit:
func _on_Button1_pressed():
var currentNumber = $NumberStuffs.get_text()
currentNumber = currentNumber + "1"
$NumberStuffs.set_text(currentNumber)
Alright, we are storing a string on the text property of the node $NumberStuffs. And we add a digit by concatenating to it.
The above code should be is equivalent to this:
func _on_Button1_pressed():
$NumberStuffs.text += "1"
If get_text and set_text are custom functions in GDScript, you may want to look into setget.
Thus, the question is how to remove the last character of a string. There are several ways!
One way would be using erase:
func _on_BDeleteDigit_pressed():
var text := $NumberStuffs.text
var length := text.length()
text.erase(length - 1, 1)
$NumberStuffs.text = text
Note that erase is modifying the string, but the string is a copy we got from reading $NumberStuffs.text (or calling $NumberStuffs.get_text), which is why we need to set to $NumberStuffs.text (or call $NumberStuffs.set_text) anyway.
Or if you prefer:
func _on_BDeleteDigit_pressed():
var text := $NumberStuffs.get_text()
var length := text.length()
text.erase(length - 1, 1)
$NumberStuffs.set_text(text)
Alternatively, we might get a string which is like the one we have except lacking the last character. We can do that with left (which lets you get a portion of the string from the left, there is also a right function that does the same but from the right):
func _on_BDeleteDigit_pressed():
var length := $NumberStuffs.text.length()
$NumberStuffs.text = $NumberStuffs.text.left(length - 1)
Or, if you prefer:
func _on_BDeleteDigit_pressed():
var text := $NumberStuffs.get_text()
var length := text.length()
$NumberStuffs.set_text(text.left(length - 1))
In general we can get a string containing a portion of another string with substr:
func _on_BDeleteDigit_pressed():
var length := $NumberStuffs.text.length()
$NumberStuffs.text = $NumberStuffs.text.substr(0, length - 1)
Or, if you prefer:
func _on_BDeleteDigit_pressed():
var text := $NumberStuffs.get_text()
var length := text.length()
$NumberStuffs.set_text(text.substr(0, length - 1))
And yes, you can modify the string by indexing it, which I believe is what you were trying. For example:
$NumberStuffs.text[-1] = "a"
Which is equivalent to:
var length := $NumberStuffs.text.length()
$NumberStuffs.text[length - 1] = "a"
Which is equivalent to:
var text := $NumberStuffs.get_text()
var length := text.length()
text[length - 1] = "a"
$NumberStuffs.set_text(text)
Will replace the last character with an "a". And yes, you could remove by doing that. That would be:
$NumberStuffs.text[-1] = ""
Which is equivalent to:
var length := $NumberStuffs.text.length()
$NumberStuffs.text[length - 1] = ""
Which is equivalent to:
var text := $NumberStuffs.get_text()
var length := text.length()
text[length - 1] = ""
$NumberStuffs.set_text(text)
By the way, I have been using := when declaring the variables. That declares the variable of the type of whatever I'm using to initialize them.

Related

How to convert interface to struct

Here is the simplified code of a cache. Suppose Container placed in a package, so it don't know about Member.
While I wanna store instances of Member in Container, So I store an empty instance of Member in Container as outerType.
In the Container->GetMysql, I fill a new variable by test values (but, in real world, It fill by data of database, dynamically).
then in the function Put, I store data in items as Cache for next uses. In the Get I get the data stored in the items.
Before this every thing is fine. My problem is where i want to convert result of Get to type of Member m = res.(Member) . How Can I convert it to an instance of Member
I found many question about this subject, but none of them solved my problem
For more detail: I want the Get return data with its pointer of where it stored in items. So if I get some variable of same member, an change in one are shown in others
package main
import (
"fmt"
"reflect"
)
type Member struct {
Id int
Name string
Credit int
Age int
}
type Container struct {
outerType interface{}
items map[string]*interface{}
}
func (cls *Container)GetMysql(s string, a int64) interface{}{
obj := reflect.New(reflect.TypeOf(cls.outerType))
elem := obj.Elem()
//elem := reflect.ValueOf(o).Elem()
if elem.Kind() == reflect.Struct {
f := elem.FieldByName("Name")
f.SetString(s)
f = elem.FieldByName("Credit")
f.SetInt(a)
}
return obj.Interface()
}
func (cls *Container)Get(value string) *interface{}{
return cls.items[value]
}
func (cls *Container)Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = &res
}
func main() {
c := Container{outerType:Member{}}
c.items = make(map[string]*interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(*res)
m := &Member{}
m = res.(Member) // Here is the problem. How to convert ?
fmt.Println(m)
}
You should hardly ever use pointer to interface. My advice is to never use it, when you'll need it, you'll know.
Instead if you need a pointer to something (so you can have the same pointer at multiple places, and so modifying the pointed value somewhere, it will have effect on the others), "wrap the pointer" in the interface value.
So first modify the items field so that it stores interface{} values instead of pointers:
items map[string]interface{}
This means no restriction: you can pass and store pointers, that's not a problem.
Next modify Get() to return interface{}:
func (cls *Container) Get(value string) interface{}{
return cls.items[value]
}
And also in Put(), don't take the address of an interface{}:
func (cls *Container) Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = res
}
And you have to type-assert *Member from the values returned by Get().
And now testing it:
c := Container{outerType: Member{}}
c.items = make(map[string]interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(res)
m := res.(*Member) // Here is the problem. How to convert ?
fmt.Println(m)
Output (try it on the Go Playground):
&{0 Jack 500 0}
&{0 Jack 500 0}
Now if you would modify a field of m:
m.Credit = 11
And then get the value form the cache:
fmt.Println(c.Get("Jack"))
We'll see the modified value, even though we did not call Put() (try it on the Go Playground):
&{0 Jack 11 0}

How do I convert a vector of strings to a vector of integers in a functional way?

I'm trying to convert Vec<&str> to Vec<u16> but I can't figure out a functional way to do it.
let foo: &str = "1,2,3"; // Parsing a string here
let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's
I need to get bar into a Vec<u16>.
There's an iterator adapter map! You'd use it like this:
let bar: Vec<u16> = foo.split(",").map(|x| x.parse::<u16>().unwrap()).collect();
parse is a library function that relies on the trait FromStr, and it can return an error, so we need to unwrap() the error type. (This is a good idea for a short example, but in real code, you will want to handle the error properly - if you have a value that's not a u16 there, your program will just crash).
map takes a closure that takes it's parameter by value and then returns the iterator obtained by lazily applying that function. You're collecting all of the values here, but if you only take(5) of them, you would only parse 5 of the strings.
You haven't fully specified your problem. Specifically, what should happen when one of the strings cannot be parsed into a number? When you parse a number from a string using parse, it can fail. That is why the function returns a Result:
fn parse<F>(&self) -> Result<F, F::Err>
where
F: FromStr,
Here's a solution that takes the vector, gets an iterator with iter, changes each item using map and ultimately returns a Result using collect. If the parsing was a success, you get an Ok. If any failed, you get an Err:
fn main() {
let input = "1,2,3";
let strings: Vec<_> = input.split(",").collect();
let numbers: Result<Vec<u16>, _> = strings.iter().map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
Or you could remove failed conversions by filtering out Err values with flat_map:
fn main() {
let input = "1,2,3";
let strings: Vec<_> = input.split(",").collect();
let numbers: Vec<u16> = strings.iter().flat_map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
Of course, it's a bit silly to convert the string into a vector of strings and then convert it again to a vector of integers. If you actually have a comma-separated string and want numbers, do it in one go:
fn main() {
let input = "1,2,3";
let numbers: Result<Vec<u16>, _> = input.split(",").map(|x| x.parse()).collect();
println!("{:?}", numbers);
}
See also:
Why does `Option` support `IntoIterator`?
My take as someone not really experienced in Rust yet.
fn main() {
let foo: &str = "1,2,3"; // Parsing a string here
let bar: Vec<&str> = foo.split(",").collect(); // Bar is a nice vector of &str's
// here the magic happens
let baz = bar.iter().map(|x| x.parse::<i64>());
for x in baz {
match x {
Ok(i) => println!("{}", i),
Err(_) => println!("parse failed"),
}
}
}
Note that since parse returns a Result, you have to extract the value from each parsed element. You might want to behave in a different way, e.g. filter only the succeeded results.

Pointer problems

TL;DR Somehow, I am appending a pointer to a list instead of the object within a for loop of objects so at the end the entire slice is composed of the same object multiple times. I just don't know how to fix that.
The Long Way
I am still having a super hard time trying to figure out pointers in go. I posted a question yesterday and got some help but now I am stuck on a slightly different issue in the same piece of code.
I am working with gocql and cqlr go packages to try and bit a small object mapper for my Cassandra queries. Essentially the problem I am having is I am appending what appears to be a pointer to an object, not a new instance of the obj to the array. How do I fix that? I have tried adding & and * in front of value but that doesn't seem to work. How do I fix these? The bind function needs an & according to their docs.
Code
type Query struct {
query string
values interface{}
attempts int
maxAttempts int
structType reflect.Type
}
func (query Query) RetryingQuery() (results []interface{}) {
var q *gocql.Query
if query.values != nil {
q = c.Session.Query(query.query, query.values)
} else {
q = c.Session.Query(query.query)
}
bindQuery := cqlr.BindQuery(q)
value := reflect.New(query.structType).Interface()
for bindQuery.Scan(value) {
fmt.Println(value)
results = append(results, value)
}
return
}
The docs ask for var value type then in bind you would pass &value. I quoted the docs below.
var t Tweet
var s []Tweet
for b.Scan(&t) {
// Application specific code goes here
append(s, t)
}
The issue is I cannot directly go var value query.structType to define its type then pass the reference of that to bindQuery.Scan().
What is printed
&{result1 x86_64 24 3.2.0-74-generic Linux}
&{result2 x86_64 24 3.19.0-25-generic Linux}
&{result3 x86_64 4 3.13.0-48-generic Linux}
&{result4 x86_64 2 3.13.0-62-generic Linux}
&{result5 x86_64 4 3.13.0-48-generic Linux}
What is in the slice
Spoiler, it is result5 repeated over and over. I understand that I am just appending the pointer to same object to the list and that every loop iteration the object is changed and that changes all the results in the slice to that new object. I just don't know how to fix it.
[{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"}]
Well I can at least tell you what you're doing. bindQuery takes a pointer. It changes the value stored at the address.
What you're essentially doing is this:
package main
import "fmt"
func main() {
var q int
myInts := make([]*int, 0, 5)
for i := 0; i < 5; i++ {
q = i
fmt.Printf("%d ", q)
myInts = append(myInts, &q)
}
fmt.Printf("\n")
for _, value := range myInts {
fmt.Printf("%d ", *value)
}
fmt.Printf("\n")
fmt.Println(myInts)
}
Which, as you can probably guess, gives you this:
0 1 2 3 4
4 4 4 4 4
[0x104382e0 0x104382e0 0x104382e0 0x104382e0 0x104382e0]
Things get a little more confusing with reflect. You can get your type as an interface, but that is it (unless you want to play with unsafe). An interface, in simple terms, contains a pointer to the original type underneath (and some other stuff). So in your function you are passing a pointer (and some other stuff). Then you're appending the pointer. It might be nice just to get concrete and type switch your interface. I assume you know what types it could be. In which case you'd have to have something along these lines:
package main
import (
"fmt"
"reflect"
)
type foo struct {
fooval string
}
type bar struct {
barval string
}
func main() {
f1 := foo{"hi"}
f2 := &foo{"hi"}
b1 := bar{"bye"}
b2 := &bar{"bye"}
doSomething(f1)
doSomething(f2)
doSomething(b1)
doSomething(b2)
}
func doSomething(i interface{}) {
n := reflect.TypeOf(i)
// get a new one
newn := reflect.New(n).Interface()
// find out what we got and handle each case
switch t := newn.(type) {
case **foo:
*t = &foo{"hi!"}
fmt.Printf("It was a **foo, here is the address %p and here is the value %v\n", *t, **t)
case **bar:
*t = &bar{"bye :("}
fmt.Printf("It was a **bar, here is the address %p and here is the value %v\n", *t, **t)
case *foo:
t = &foo{"hey!"}
fmt.Printf("It was a *foo, here is the address %p and here is the value %v\n", t, *t)
case *bar:
t = &bar{"ahh!"}
fmt.Printf("It was a *bar, here is the address %p and here is the value %v\n", t, *t)
default:
panic("AHHHH")
}
}
You could also just keep calling value = reflect.New(query.structType).Interface() inside of the loop which will give you new interfaces every time. Reassigning value after every append. Last time through the loop would make one extra though..

How to get underlying value from a reflect.Value in golang?

So I found some code that help me get started with reflection in Go (golang), but I'm having trouble getting a the underlying value so that I can basically create a map[string]string from a struct and it's fields.
Eventually, I'd like to make the result into a map[string]interface{}, but this one issue is kind of blocking me.
The code I have at the moment:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
FirstName string `tag_name:"tag 1"`
LastName string `tag_name:"tag 2"`
Age int `tag_name:"tag 3"`
}
func inspect(f interface{}) map[string]string {
m := make(map[string]string)
val := reflect.ValueOf(f).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
f := valueField.Interface()
val := reflect.ValueOf(f)
m[typeField.Name] = val.String()
}
return m
}
func dump(m map[string]string) {
for k, v := range m {
fmt.Printf("%s : %s\n", k, v)
}
}
func main() {
f := &Foo{
FirstName: "Drew",
LastName: "Olson",
Age: 30,
}
a := inspect(f)
dump(a)
}
The output from running the code:
FirstName : Drew
LastName : Olson
Age : <int Value>
From what I understand the output for FirstName and LastName are actual reflect.Value objects but for strings the String() method on value just outputs the underlying String. I'd like to either get the int and change it into a string, but from the relfect package documentation I'm not immediately seeing how that's done.
Soo.... How do I get the underlying value from a reflect.Value in golang?
A good example of how to parse values is the fmt package. See this code.
Using the mentioned code to match your problem would look like this:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
m[typeField.Name] = val.String()
// etc...
}
Basically you need to check for all available Kinds.
It looks like you're on the right track. The problem I see with your code is it makes assumptions about the values, meaning when do you call Elem() and how many times (to resolve pointers). In order to know this you need to look at the reflect.Kind. Is the value a reflect.Ptr? Then use Elem().
Once you have the value from val.Interface() / val.String() / val.Int() you can convert your values as needed. What you use is going to depend on reflect.Kind. To convert an int to/from string you need to use the strconv package.
The encoding/json and encoding/xml packages do this kind of work already. The source code provides some great examples. For example, take a look at copyValue in encoding/xml/read.go and marshalSimple in encoding/xml/marshal.go.
This should be easier to do with Go 1.5 (August 2015)
See review 8731 and commit 049b89d by Rob Pike (robpike):
fmt: treat reflect.Value specially - as the value it holds
This would allow you to print the actual value of a Reflect.Value() argument:
When a reflect.Value is passed to Printf (etc.), fmt called the String method, which does not disclose its contents.
To get the contents, one could call Value.Interface(), but that is illegal
if the Value is not exported or otherwise forbidden.
This CL improves the situation with a trivial change to the fmt package: when we see a reflect.Value as an argument, we treat it exactly as we treat a reflect.Value we make inside the package.
This means that we always print the contents of the Value as if that was the argument to Printf.
This is arguably a breaking change but I think it is a genuine improvement and no greater a break than many other tweaks we have made to formatted output from this package.
Another simple solution can be ,
flavorName = fmt.Sprintf("%v",strct)
" fmt.Sprintf() " will return the value which can be stored in a variable.

How to check if a map contains a key in Go?

I know I can iterate over a map m with
for k, v := range m { ... }
and look for a key, but is there a more efficient way of testing for a key's existence in a map?
Here's how you check if a map contains a key.
val, ok := myMap["foo"]
// If the key exists
if ok {
// Do something
}
This initializes two variables. val is the value of "foo" from the map if it exists, or a "zero value" if it doesn't (in this case the empty string). ok is a bool that will be set to true if the key existed.
If you want, you can shorten this to a one-liner.
if val, ok := myMap["foo"]; ok {
//do something here
}
Go allows you to put an initializing statement before the condition (notice the semicolon) in the if statement. The consequence of this is that the scope ofval and ok will be limited to the body of the if statement, which is helpful if you only need to access them there.
In addition to The Go Programming Language Specification, you should read Effective Go. In the section on maps, they say, amongst other things:
An attempt to fetch a map value with a key that is not present in the
map will return the zero value for the type of the entries in the map.
For instance, if the map contains integers, looking up a non-existent
key will return 0. A set can be implemented as a map with value type
bool. Set the map entry to true to put the value in the set, and then
test it by simple indexing.
attended := map[string]bool{
"Ann": true,
"Joe": true,
...
}
if attended[person] { // will be false if person is not in the map
fmt.Println(person, "was at the meeting")
}
Sometimes you need to distinguish a missing entry from a zero value.
Is there an entry for "UTC" or is that 0 because it's not in the map
at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this
example, if tz is present, seconds will be set appropriately and ok
will be true; if not, seconds will be set to zero and ok will be
false. Here's a function that puts it together with a nice error
report:
func offset(tz string) int {
if seconds, ok := timeZone[tz]; ok {
return seconds
}
log.Println("unknown time zone:", tz)
return 0
}
To test for presence in the map without worrying about the actual
value, you can use the blank identifier (_) in place of the usual
variable for the value.
_, present := timeZone[tz]
Searched on the go-nuts email list and found a solution posted by Peter Froehlich on 11/15/2009.
package main
import "fmt"
func main() {
dict := map[string]int {"foo" : 1, "bar" : 2}
value, ok := dict["baz"]
if ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
}
Or, more compactly,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
Note, using this form of the if statement, the value and ok variables are only visible inside the if conditions.
Short Answer
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
Example
Here's an example at the Go Playground.
Longer Answer
Per the Maps section of Effective Go:
An attempt to fetch a map value with a key that is not present in the map will return the zero value for the type of the entries in the map. For instance, if the map contains integers, looking up a non-existent key will return 0.
Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false. Here's a function that puts it together with a nice error report:
func offset(tz string) int {
if seconds, ok := timeZone[tz]; ok {
return seconds
}
log.Println("unknown time zone:", tz)
return 0
}
To test for presence in the map without worrying about the actual value, you can use the blank identifier (_) in place of the usual variable for the value.
_, present := timeZone[tz]
Have a look at this snippet of code
nameMap := make(map[string]int)
nameMap["river"] = 33
v ,exist := nameMap["river"]
if exist {
fmt.Println("exist ",v)
}
As noted by other answers, the general solution is to use an index expression in an assignment of the special form:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
This is nice and clean. It has some restrictions though: it must be an assignment of special form. Right-hand side expression must be the map index expression only, and the left-hand expression list must contain exactly 2 operands, first to which the value type is assignable, and a second to which a bool value is assignable. The first value of the result of this special form will be the value associated with the key, and the second value will tell if there is actually an entry in the map with the given key (if the key exists in the map). The left-hand side expression list may also contain the blank identifier if one of the results is not needed.
It's important to know that if the indexed map value is nil or does not contain the key, the index expression evaluates to the zero value of the value type of the map. So for example:
m := map[int]string{}
s := m[1] // s will be the empty string ""
var m2 map[int]float64 // m2 is nil!
f := m2[2] // f will be 0.0
fmt.Printf("%q %f", s, f) // Prints: "" 0.000000
Try it on the Go Playground.
So if we know that we don't use the zero value in our map, we can take advantage of this.
For example if the value type is string, and we know we never store entries in the map where the value is the empty string (zero value for the string type), we can also test if the key is in the map by comparing the non-special form of the (result of the) index expression to the zero value:
m := map[int]string{
0: "zero",
1: "one",
}
fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
m[0] != "", m[1] != "", m[2] != "")
Output (try it on the Go Playground):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
In practice there are many cases where we don't store the zero-value value in the map, so this can be used quite often. For example interfaces and function types have a zero value nil, which we often don't store in maps. So testing if a key is in the map can be achieved by comparing it to nil.
Using this "technique" has another advantage too: you can check existence of multiple keys in a compact way (you can't do that with the special "comma ok" form). More about this: Check if key exists in multiple maps in one condition
Getting the zero value of the value type when indexing with a non-existing key also allows us to use maps with bool values conveniently as sets. For example:
set := map[string]bool{
"one": true,
"two": true,
}
fmt.Println("Contains 'one':", set["one"])
if set["two"] {
fmt.Println("'two' is in the set")
}
if !set["three"] {
fmt.Println("'three' is not in the set")
}
It outputs (try it on the Go Playground):
Contains 'one': true
'two' is in the set
'three' is not in the set
See related: How can I create an array that contains unique strings?
var d map[string]string
value, ok := d["key"]
if ok {
fmt.Println("Key Present ", value)
} else {
fmt.Println(" Key Not Present ")
}
var empty struct{}
var ok bool
var m map[string]struct{}
m = make(map[string]struct{})
m["somestring"] = empty
_, ok = m["somestring"]
fmt.Println("somestring exists?", ok)
_, ok = m["not"]
fmt.Println("not exists?", ok)
Then, go run maps.go
somestring exists? true
not exists? false
It is mentioned under "Index expressions".
An index expression on a map a of type map[K]V used in an assignment
or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
yields an additional untyped boolean value. The value of ok is true if
the key x is present in the map, and false otherwise.
A two value assignment can be used for this purpose. Please check my sample program below
package main
import (
"fmt"
)
func main() {
//creating a map with 3 key-value pairs
sampleMap := map[string]int{"key1": 100, "key2": 500, "key3": 999}
//A two value assignment can be used to check existence of a key.
value, isKeyPresent := sampleMap["key2"]
//isKeyPresent will be true if key present in sampleMap
if isKeyPresent {
//key exist
fmt.Println("key present, value = ", value)
} else {
//key does not exist
fmt.Println("key does not exist")
}
}
Example usage: Looping through a slice, for pairMap checking if key exists.
It an algorithm to find all pairs that adds to a specific sum.
func findPairs(slice1 []int, sum int) {
pairMap := make(map[int]int)
for i, v := range slice1 {
if valuei, ok := pairMap[v]; ok {
fmt.Println("Pair Found", i, valuei)
} else {
pairMap[sum-v] = i
}
}
}

Resources