The irregularity of the principal parts is due to their disparate origin in definitely two and possibly three distinct Indo-European roots.
Unlike every other English verb except be, the preterite (simple past tense) of go is not etymologically related to its infinitive.
[1] Old English did not use any variation of went for the general preterite of go; instead, the word ēode (variant ġeēode) was used, which lingered on as the now obsolete yede, yode and yead.
[5] One reflex of *h₁ey- is Latin īre 'to go' (present eō 'I go') which gave many English words such as ambition, exit, introit, issue, preterite, and so forth.
In Northern English and Scots, yede was gaed, regularly formed by suffixing -ed to a variant of go.
PGmc *windaną comes from Proto-Indo-European *wendʰ- 'to wind, twist', which also gave Umbrian preuenda 'turn!'
(imperative), Tocharian A/B wänt/wänträ 'covers, envelops', Greek (Hesychius) áthras 'wagon', Armenian gind 'ring', and Sanskrit vandhúra 'carriage framework'.
These forms are relics from earlier, more widespread words that meant 'to walk, go' and which survive sporadically in Scots gang, East Frisian gunge, and Icelandic ganga.
These are reflexes of Proto-Germanic *ganganą, from Proto-Indo-European *ǵʰengʰ- 'to step', which also gave Lithuanian žeñgti 'to stride', Greek kochōnē 'perineum', Avestan zanga 'ankle', and Sanskrit jáṁhas 'step', jaṅghā 'shank'.
Therefore, the case of English go is not unique among the Germanic languages, and it would appear that most have in a like manner reproduced equivalent suppletive conjugations for their words for 'to go', suggesting a cyclical change patterned after the state of affairs in Proto-Germanic.