等价于c类型

What are the right equivalent of unsigned char or unsigned char* in go? Or am I even doing this right?


I have this C++ class:

class ArcfourPRNG
{
public:
    ArcfourPRNG();
    void SetKey(unsigned char *pucKeyData, int iKeyLen);
    void Reset();
    unsigned char Rand();

private:
    bool m_bInit;
    unsigned char m_aucState0[256];
    unsigned char m_aucState[256];
    unsigned char m_ucI;
    unsigned char m_ucJ;
    unsigned char* m_pucState1;
    unsigned char* m_pucState2;
    unsigned char m_ucTemp;
};

I am trying to rewrite it to go:

type ArcfourPRNG struct {
    m_bInit bool
    m_aucState0 [256]byte
    m_aucState [256]byte
    m_ucI, m_ucJ []byte
    *m_pucState1 []byte
    *m_pucState2 []byte
    m_ucTemp []byte
}

func (arc4 *ArcfourPRNG) SetKey(pucKeyData []byte, iKeyLen int) {
func (arc4 *ArcfourPRNG) Reset() {
func (arc4 *ArcfourPRNG) Rand() uint {

Well, I just started with go a few hours ago. So this is still confusing me.


A function

for(i=0; i<256; i++)
{
    m_pucState1 = m_aucState0 + i;
    m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
    m_pucState2 = m_aucState0 + m_ucJ;
    //Swaping
    m_ucTemp = *m_pucState1;
    *m_pucState1 = *m_pucState2;
    *m_pucState2 = m_ucTemp;
    m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256); // copy(aucState[:], aucState0) ?

Hopefully this can clear a few things up for you.

  • For storing raw sequences of bytes, use a slice []byte. If you know exactly how long the sequence will be, you can specify that, e.g. [256]byte but you cannot resize it later.
  • While Go has pointers, it does not have pointer arithmetic. So you will need to use integers to index into your slices of bytes.
  • For storing single bytes, byte is sufficient; you don't want a slice of bytes. Where there are pointers in the C++ code used to point to specific locations in the array, you'll simply have an integer index value that selects one element of a slice.
  • Go strings are not simply sequences of bytes, they are sequences of UTF-8 characters stored internally as runes, which may have different lengths. So don't try to use strings for this algorithm.

To reimplement the algorithm shown, you do not need either pointers or pointer arithmetic at all. Instead of keeping pointers into the byte arrays as you would in C++, you'll use int indexes into the slices.

This is kind of hard to follow since it's virtually all pointer arithmetic. I would want to have a description of the algorithm handy while converting this (and since this is probably a well-known algorithm, that should not be hard to find). I'm not going to do the entire conversion for you, but I'll demonstrate with hopefully a simpler example. This prints each character of a string on a separate line.

C++:

unsigned char *data = "Hello World";
unsigned char *ptr = 0;

for (int i = 0; i < std::strlen(data); i++) {
    ptr = i + data;
    std::cout << *ptr << std::endl;
}

Go:

data := []byte("Hello World")

for i := 0; i < len(data); i++ {
    // The pointer is redundant already
    fmt.Println(data[i:i+1])
}

So, learn about Go slices, and when you do reimplement this algorithm you will likely find the code to be somewhat simpler, or at least easier to understand, than its C++ counterpart.