On Tue, Sep 13, 2016 at 3:31 PM <davidmiller...@gmail.com> wrote:

> I've spent many, many, many hours on this (measured in days, at this
> point) and I'm convinced that Golang is missing a fundamental programming
> capability, that of multidimensional associative arrays. Searching through
> this forum's archives and other sites, I've found that I'm not the first
> one to face this problem and no one who has posted about this has yet
> received a decent response (at least, not one that I have found)! The best
> responses consist either of maps that are, at most, two levels deep or maps
> whose depth is known in advance and declared using something like
> make(map[string]map[string]map[string]map[string]map[string]string) and
> even in those cases, one cannot replace a map with just a string on any of
> those levels.
>
> This is a MAJOR missing feature in Golang.
>
> In PHP, for example, multidimensional associative arrays are declarable
> and usable in a single line of code. In Javascript, Objects can serve that
> purpose and those serve as the foundation of pretty much the entire
> language. HTML is built on the tree structure, which is essentially just a
> multimentional array. The Internet is essentiallly built on it
> multidimensional associative arrays! Take XML or JSON, both of which are
> essentially multidimensional associative arrays. Take the file/folder
> system on your desktop computers and on servers as another example. Take
> relational database recordsets. I mean, the list goes on and on and on! How
> can Golang not have a simple way to initialize, manipulate and maintain
> multidimensional associative arrays?????
>
> This is such a big problem that I've even spent time looking into
> alternate options to Golang, such as Clojure, Erlang and Elixir, and I'm
> quite certain others have followed my route. I am not about to give up on
> Golang just yet, because it would mean a tremendous amount of rewriting
> what I've already done and learning yet another new language, but this is a
> very serious missing piece in Golang.
>
> It's incredible that this has gone overlooked in Golang for so long. The
> posts I found were from as early as 2012! This is a very disappointing
> discovery. I have found many things about Golang that I really like and
> many things about Golang that I really don't like, but the lack of
> multidimensional associative arrays beats out even the lack of decent
> global error handling! By the way, while I'm at it are there any libraries
> for that?
>
> Is there any of doing multidimensional associative arrays in Golang
> (beyond two levels and without specifying the depth of the array or map in
> advance) or am I wasting my time on this problem? If not, does anyone know
> if this feature is planned for an upcoming version of Golang?
>

When you say this is a missing feature of Go and that you can't imagine how
Go programmers have expressed solutions to common problems without it, I
interpret that as (and I apologize that you probably won't agree) "this
approach that I do in PHP or Javascript does work exactly the same way in
Go, so I am calling it a missing feature". The thing is, PHP and Javascript
are both dynamically typed languages. They would both allow you to shove
any types that you want, mixed, into data structures. Thus you would be
able to express your map of strings to either a string or another map. In a
statically-type language like Go, you have to either be explicit about the
concrete types you are storing, or you have to use interfaces/reflection in
order to mix types with common behaviour and then inspect and extract the
concrete type or call the interface methods.

Because I am more familiar with Python than PHP/JS, let me use that as a
comparison. In Python you can create a dictionary with any kind of hashable
key type and any value, mixed:

aDict = {
    (1, 2, 'c'): "value",
    'string': {'another': 'value'},
    1: ['a', 'b', 3],
}

​
But really every object in Python is just a C wrapper object called a
PyObject (that is, in CPython). Python will then dynamically evaluate the
type and resolve methods and operations on them as needed. When you have a
mixed dictionary (multi-dimensional associative array) of more nested dicts
and string values, it allows you to do things like:   aDict['a']['b']['c']
because on-the-fly, Python would try and treat each value as a dict and it
would either work at runtime. or raise an exception if the object stored at
that point did not support the operation.
Go, being a statically typed language, can have the mixed types, but the
1-to-1 equivalent (or closest translation) of a "GoObject" (PyObject) would
be interfaces. And then you need to manually assert the type, whereas
Python would be doing it dynamically when you simply try to use the object,
because that is how it does it for all objects whenever you access them.

But honestly, with all the examples you listed in the world of
tree-structured data, that does not mean it needs to be modelled with
nested maps. It is just the fact that you had the dynamically typed
associative arrays available to you in PHP and JS, and that is your goto
data structure. There are other solutions as well, such as a "Node" struct
which can store data and point at one or more other Node objects. Obviously
that means you have to iterate down to your value instead of doing
something like aDict['a']['b']['c'], but like I said, in a language that
doen't let you mix concrete types in a single data structure, how else
would you be able to store both maps and string values at the same level?
They have to conform to some kind of concrete type or interface. Go is not
PHP or JS. And I am pretty confident that a number of existing Go projects
have been able to model tree structures successfully up to this point.


>
> On Monday, September 12, 2016 at 1:28:26 AM UTC-4, davidmi...@gmail.com
> wrote:
>>
>> *I have two Golang questions that I hope someone could help me out with.*
>>
>>
>> *1) Am I misunderstanding Golang maps?*
>>
>>
>> *I'm trying to translate a project from PHP to Golang for the websockets
>> and the concurrency. *
>>
>>
>> *However, I can't do this.....*
>>
>>
>> *          var MyArray [string]string*
>>
>>
>> *Instead, I have to do this.....*
>>
>>
>> *          var MyMap map[string]string*
>>
>>
>> *However, since the same array (map) would be used at least once for each
>> call to the Golang code from the Front End, which occurs any time a user
>> sends data to the Back End, I have been led to believe that I would have to
>> lock and unlock the map for each use. Wouldn't that essentially break
>> concurrency (or at least eliminate its benefits??? No other user's function
>> could use this map until the current user's function is done with it. I'd
>> be back to "single threaded" again (concurrently speaking). This would
>> defeat much of the point in my switching the project from PHP to Golang. To
>> maintain concurrency without blocking other users, one would have to avoid
>> using maps. Arrays (maps) are central to programming. How does anyone get
>> by in Golang without using Maps?????*
>>
>>
>> *For example, if I do the following.....*
>>
>>
>> *func MyFunc (whatever) *map[string]string *{*
>>
>>
>>      var MyMap map[string]string
>>
>>
>> *     // Do something with the map*
>>
>>
>> *     return MyMap*
>>
>>
>> *}*
>>
>>
>> *func CallingFunction (whatever) {*
>>
>>
>> *     MyReturnedMap := go  MyFunc(whatever)*
>>
>>
>> *}*
>>
>>
>> *.....would I have to lock and unlock the map or are two separate
>> instances of the map declared?*
>>
>>
>> *Again, am** I misunderstanding Golang maps?*
>>
>>
>> *2) Also, how would one build a multidimensional array with a string
>> index (or even a map of maps) for something like a large file directory
>> where the number of files, folders and levels are unknown at the outset
>> (without repeatedly using the append function that apparently uses memory
>> on an exponential scale of 2^x)? I've figured out how to do
>> map[string]map[string]map[string]string, but one would have to know how
>> many levels there would be, in advance, to be able to use something like
>> that. Also, when I've tried that, I can't put a string on any level except
>> for the last one, since the only data type that any level other than the
>> last one will accept is another map! What if the map turns out to be only
>> three levels deep for one path and five levels deep for another path?** I've
>> tried the following, which I found online, but I can't dynamically add any
>> new folders to the directory with any kind of ease. It seems that
>> initializing the struct is the only way to get data into the struct without
>> declaring a new struct for every manipulation!*
>>
>>
>> *(Below code from 
>> **http://stackoverflow.com/questions/19080116/golang-tree-like-solution-for-filesystem
>> <http://stackoverflow.com/questions/19080116/golang-tree-like-solution-for-filesystem>)*
>>
>>
>> package Websocket
>>
>> import "fmt"
>>
>> type File struct {
>>        Name string
>> }
>>
>> type Folder struct {
>>        Name    string
>>        Files   []File
>>        Folders []Folder
>> }
>>
>> func main() {
>>        root := Folder{
>>               Name: "Root",
>>               Files: []File{
>>                      {"One"},
>>                      {"Two"},
>>               },
>>               Folders: []Folder{
>>                      {
>>                             Name: "Empty",
>>                      },
>>               },
>>        }
>>        fmt.Printf("Root %#v\n", root)
>> }
>>
>>
>> *Given the above, how would i now add another folder to the directory tree. 
>> Among many other variations, I've tried the following.....*
>>
>>
>> *root.Folders[0].Name = "MyFirstFolder"*
>>
>>
>> *.....but nothing I have tried has worked.*
>>
>>
>> *What I've been trying to do is set up an array that looks like the 
>> following.....*
>>
>>
>> *MyArray["Number of Sub Items"] = 6*
>>
>> *MyArray["Type of Sub Items"] = "Folders"*
>>
>> *MyArray[0] = "Folder 1"*
>>
>> *MyArray[1]** = "Folder 2"*
>>
>> *MyArray[2]** = "Folder 3"*
>>
>> *MyArray[3]** = "Folder 4"*
>>
>> *MyArray[4]** = "Folder 5"*
>>
>> *MyArray[6]** = "Folder 6"*
>>
>>
>> *MyArray[3]**["Number of Sub Items"]** = 3*
>>
>> *MyArray["Type of Sub Items"] = "Folders"*
>>
>> *MyArray[3][0] = "Folder 1"*
>>
>> *MyArray[3][1]** = "Folder 2"*
>>
>> *MyArray[3][2]** = "Folder 3"*
>>
>>
>> *Note that this problem is not exclusive to directory structure. Using 
>> directory structure is just a simple way to describe the problem I'm having.*
>>
>>
>> *Alternatively**, are there any libraries that can do the above so that I 
>> don't have to "reinvent the wheel"?*
>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to